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 / pricing-slider / index.js

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

350 lines 22.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 useState = wp.element.useState;
4 var Fragment = wp.element.Fragment;
5 var registerBlockType = wp.blocks.registerBlockType;
6 var useBlockProps = wp.blockEditor.useBlockProps;
7 var InspectorControls = wp.blockEditor.InspectorControls;
8 var PanelColorSettings = wp.blockEditor.PanelColorSettings;
9 var RichText = wp.blockEditor.RichText;
10 var PanelBody = wp.components.PanelBody;
11 var RangeControl = wp.components.RangeControl;
12 var ToggleControl = wp.components.ToggleControl;
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 registerBlockType('blockenberg/pricing-slider', {
20 edit: function (props) {
21 var a = props.attributes;
22 var set = props.setAttributes;
23 var blockProps = useBlockProps();
24
25 var _state = useState(a.initialTier || 1);
26 var tierIdx = _state[0];
27 var setTier = _state[1];
28
29 var _bill = useState(false); // false = monthly, true = annual
30 var isAnnual = _bill[0];
31 var setBill = _bill[1];
32
33 var tiers = a.tiers || [];
34 var tier = tiers[Math.min(tierIdx, tiers.length - 1)] || {};
35 var disc = a.annualDiscount || 20;
36 var rawPrice = tier.monthlyPrice || 0;
37 var price = isAnnual ? Math.round(rawPrice * (1 - disc / 100)) : rawPrice;
38
39 function updateTier(idx, field, val) {
40 var nt = a.tiers.map(function (t, i) {
41 return i === idx ? Object.assign({}, t, { [field]: val }) : t;
42 });
43 set({ tiers: nt });
44 }
45 function updateFeatures(idx, featStr) {
46 var feats = featStr.split('\n').map(function (f) { return f.trim(); }).filter(Boolean);
47 updateTier(idx, 'features', feats);
48 }
49 function addTier() {
50 set({ tiers: a.tiers.concat([{ label: 'New Tier', users: 'Custom', monthlyPrice: 149,
51 features: ['Feature one', 'Feature two'] }]) });
52 }
53 function removeTier(idx) {
54 if (a.tiers.length <= 1) return;
55 set({ tiers: a.tiers.filter(function (_, i) { return i !== idx; }) });
56 }
57
58 var sectionStyle = {
59 background: a.sectionBg || '#f8fafc',
60 padding: '60px 32px', textAlign: 'center',
61 borderRadius: 12
62 };
63 var cardStyle = {
64 background: a.cardBg || '#ffffff',
65 borderRadius: (a.cardRadius || 24) + 'px',
66 padding: '40px',
67 maxWidth: 480, margin: '0 auto',
68 boxShadow: '0 4px 24px rgba(0,0,0,0.08)',
69 border: '2px solid ' + (a.accentColor || '#6366f1')
70 };
71
72 return el('div', blockProps,
73 el(InspectorControls, {},
74 el(PanelBody, { title: 'Pricing Tiers', initialOpen: true },
75 (a.tiers || []).map(function (tier, i) {
76 return el('div', { key: i, style: { marginBottom: 14, padding: 10,
77 background: i === tierIdx ? '#ede9fe' : '#f8fafc',
78 borderRadius: 6, border: '1px solid #e5e7eb' } },
79 el('strong', { style: { display: 'flex', justifyContent: 'space-between', marginBottom: 6, fontSize: 12 } },
80 'Tier ' + (i + 1) + ': ' + (tier.label || ''),
81 el(Button, { isDestructive: true, isSmall: true,
82 onClick: function () { removeTier(i); } }, '')
83 ),
84 el(TextControl, { label: 'Label', value: tier.label || '',
85 onChange: function (v) { updateTier(i, 'label', v); }, __nextHasNoMarginBottom: true }),
86 el(TextControl, { label: 'User count label', value: tier.users || '',
87 onChange: function (v) { updateTier(i, 'users', v); }, __nextHasNoMarginBottom: true }),
88 el(TextControl, { label: 'Monthly price (number)', value: String(tier.monthlyPrice || 0),
89 type: 'number',
90 onChange: function (v) { updateTier(i, 'monthlyPrice', Number(v)); }, __nextHasNoMarginBottom: true }),
91 el(TextControl, { label: 'Features (one per line)',
92 value: (tier.features || []).join('\n'),
93 onChange: function (v) { updateFeatures(i, v); },
94 help: 'One feature per line',
95 __nextHasNoMarginBottom: true })
96 );
97 }),
98 el(Button, { isPrimary: true, isSmall: true, onClick: addTier, style: { marginTop: 4 } }, '+ Add Tier')
99 ),
100 el(PanelBody, { title: 'Section Settings', initialOpen: false },
101 el(RichText, { tagName: 'p',
102 value: a.heading, onChange: function (v) { set({ heading: v }); },
103 placeholder: 'Section heading', __nextHasNoMarginBottom: true }),
104 el(ToggleControl, { label: 'Show billing toggle', checked: a.showBilling !== false,
105 onChange: function (v) { set({ showBilling: v }); }, __nextHasNoMarginBottom: true }),
106 el(RangeControl, { label: 'Annual discount (%)', value: a.annualDiscount || 20,
107 onChange: function (v) { set({ annualDiscount: v }); }, min: 0, max: 60, __nextHasNoMarginBottom: true }),
108 el(TextControl, { label: 'Currency symbol', value: a.currency || '$',
109 onChange: function (v) { set({ currency: v }); }, __nextHasNoMarginBottom: true }),
110 el(TextControl, { label: 'Period label', value: a.period || '/month',
111 onChange: function (v) { set({ period: v }); }, __nextHasNoMarginBottom: true }),
112 el(TextControl, { label: 'CTA button text', value: a.ctaText || '',
113 onChange: function (v) { set({ ctaText: v }); }, __nextHasNoMarginBottom: true })
114 ),
115 el(PanelBody, { title: 'Typography', initialOpen: false },
116 (function () {
117 var TC = getTypoControl();
118 if (!TC) return el('p', null, 'Loading\u2026');
119 return el(Fragment, null,
120 el(TC, { label: 'Heading', value: a.headingTypo, onChange: function (v) { set({ headingTypo: v }); } }),
121 el(TC, { label: 'Subheading', value: a.subheadingTypo, onChange: function (v) { set({ subheadingTypo: v }); } }),
122 el(TC, { label: 'Price', value: a.priceTypo, onChange: function (v) { set({ priceTypo: v }); } }),
123 el(TC, { label: 'CTA Button', value: a.ctaTypo, onChange: function (v) { set({ ctaTypo: v }); } }),
124 el(TC, { label: 'Feature', value: a.featureTypo, onChange: function (v) { set({ featureTypo: v }); } })
125 );
126 })(),
127 el(RangeControl, { label: 'Card radius', value: a.cardRadius || 24,
128 onChange: function (v) { set({ cardRadius: v }); }, min: 0, max: 60, __nextHasNoMarginBottom: true })
129 ),
130 el(PanelColorSettings, SelectControl, {
131 title: 'Colors', initialOpen: false,
132 colorSettings: [
133 { label: 'Section background', value: a.sectionBg, onChange: function (v) { set({ sectionBg: v || '#f8fafc' }); } },
134 { label: 'Card background', value: a.cardBg, onChange: function (v) { set({ cardBg: v || '#ffffff' }); } },
135 { label: 'Heading color', value: a.headingColor, onChange: function (v) { set({ headingColor: v || '#1e1b4b' }); } },
136 { label: 'Price color', value: a.priceColor, onChange: function (v) { set({ priceColor: v || '#6366f1' }); } },
137 { label: 'Feature text', value: a.featureColor, onChange: function (v) { set({ featureColor: v || '#374151' }); } },
138 { label: 'Accent / border', value: a.accentColor, onChange: function (v) { set({ accentColor: v || '#6366f1' }); } },
139 { label: 'CTA button bg', value: a.ctaBg, onChange: function (v) { set({ ctaBg: v || '#6366f1' }); } },
140 { label: 'CTA text', value: a.ctaColor, onChange: function (v) { set({ ctaColor: v || '#ffffff' }); } },
141 { label: 'Slider color', value: a.sliderColor, onChange: function (v) { set({ sliderColor: v || '#6366f1' }); } },
142 { label: 'Track background', value: a.trackBg, onChange: function (v) { set({ trackBg: v || '#e5e7eb' }); } },
143 { label: 'Check icon color', value: a.checkColor, onChange: function (v) { set({ checkColor: v || '#6366f1' }); } }
144 ],
145 disableCustomGradients: true
146 })
147 ),
148
149 // ── Editor preview ──────────────────────────────────
150 el('div', { style: sectionStyle },
151 el(RichText, { tagName: 'h2', value: a.heading,
152 onChange: function (v) { set({ heading: v }); },
153 placeholder: 'Section heading…',
154 className: 'bkbg-psl-heading',
155 style: { color: a.headingColor || '#1e1b4b',
156 margin: '0 0 12px' }
157 }),
158 el(RichText, { tagName: 'p', value: a.subheading,
159 onChange: function (v) { set({ subheading: v }); },
160 placeholder: 'Subheading…',
161 className: 'bkbg-psl-subheading',
162 style: { color: '#64748b', margin: '0 0 32px' }
163 }),
164
165 // Billing toggle
166 a.showBilling !== false && el('div', {
167 style: { display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 12, marginBottom: 32 }
168 },
169 el('span', { style: { fontWeight: isAnnual ? 400 : 700, color: a.headingColor || '#1e1b4b' } }, 'Monthly'),
170 el('div', {
171 onClick: function () { setBill(!isAnnual); },
172 style: {
173 width: 48, height: 26, borderRadius: 13,
174 background: isAnnual ? (a.accentColor || '#6366f1') : '#d1d5db',
175 position: 'relative', cursor: 'pointer', transition: 'background .2s'
176 }
177 },
178 el('div', { style: {
179 width: 20, height: 20, borderRadius: '50%', background: '#fff',
180 position: 'absolute', top: 3, left: isAnnual ? 25 : 3,
181 transition: 'left .2s', boxShadow: '0 1px 4px rgba(0,0,0,0.2)'
182 } })
183 ),
184 el('span', { style: { fontWeight: isAnnual ? 700 : 400, color: a.headingColor || '#1e1b4b' } },
185 'Annual ',
186 el('span', { style: { background: '#dcfce7', color: '#16a34a', padding: '2px 8px',
187 borderRadius: 10, fontSize: 12, fontWeight: 600 } },
188 '-' + disc + '%')
189 )
190 ),
191
192 // Slider
193 el('div', { style: { maxWidth: 480, margin: '0 auto 32px' } },
194 el('div', { style: { display: 'flex', justifyContent: 'space-between', marginBottom: 8 } },
195 (tiers).map(function (t, i) {
196 return el('span', { key: i, style: {
197 fontSize: 12, fontWeight: i === tierIdx ? 700 : 400,
198 color: i === tierIdx ? (a.accentColor || '#6366f1') : '#64748b'
199 } }, t.label || '');
200 })
201 ),
202 el('input', {
203 type: 'range', min: 0, max: tiers.length - 1, step: 1, value: tierIdx,
204 onChange: function (e) { setTier(Number(e.target.value)); },
205 style: { width: '100%', accentColor: a.sliderColor || '#6366f1', cursor: 'pointer' }
206 })
207 ),
208
209 // Pricing card
210 el('div', { style: cardStyle },
211 el('div', { style: { marginBottom: 4, fontSize: 13, fontWeight: 600, color: a.accentColor || '#6366f1', textTransform: 'uppercase', letterSpacing: '0.08em' } }, tier.label || ''),
212 el('div', { style: { marginBottom: 4, fontSize: 13, color: '#64748b' } }, tier.users || ''),
213 el('div', { style: { margin: '16px 0', display: 'flex', alignItems: 'flex-end', justifyContent: 'center', gap: 4 } },
214 el('span', { style: { fontSize: 24, fontWeight: 700, color: a.priceColor || '#6366f1', alignSelf: 'flex-start', marginTop: 8 } }, a.currency || '$'),
215 el('span', { className: 'bkbg-psl-amount', style: { color: a.priceColor || '#6366f1', lineHeight: 1 } }, price),
216 el('span', { style: { fontSize: 15, color: '#64748b', marginBottom: 6 } }, a.period || '/month')
217 ),
218 isAnnual && el('div', { style: { marginBottom: 16, fontSize: 13, color: '#16a34a', fontWeight: 600 } },
219 'Billed annually — save ' + disc + '%'),
220 el('div', { style: { marginBottom: 24 } },
221 (tier.features || []).map(function (f, i) {
222 return el('div', { key: i, style: { display: 'flex', alignItems: 'center', gap: 10,
223 marginBottom: 10, color: a.featureColor || '#374151' } },
224 el('span', { style: { color: a.checkColor || '#6366f1', fontWeight: 700, flexShrink: 0 } }, ''),
225 f
226 );
227 })
228 ),
229 el('button', { className: 'bkbg-psl-cta', style: {
230 width: '100%', padding: '14px',
231 border: 'none', borderRadius: 12, cursor: 'pointer',
232 background: a.ctaBg || '#6366f1', color: a.ctaColor || '#ffffff'
233 } }, a.ctaText || 'Get Started')
234 )
235 )
236 );
237 },
238
239 save: function (props) {
240 var a = props.attributes;
241 var blockProps = useBlockProps.save();
242 var opts = {
243 tiers: a.tiers || [],
244 showBilling: a.showBilling !== false,
245 annualDiscount: a.annualDiscount || 20,
246 currency: a.currency || '$',
247 period: a.period || '/month',
248 ctaText: a.ctaText || 'Get Started',
249 priceSize: a.priceSize || 56,
250 cardRadius: a.cardRadius || 24,
251 sectionBg: a.sectionBg || '#f8fafc',
252 cardBg: a.cardBg || '#ffffff',
253 headingColor: a.headingColor || '#1e1b4b',
254 priceColor: a.priceColor || '#6366f1',
255 featureColor: a.featureColor || '#374151',
256 accentColor: a.accentColor || '#6366f1',
257 ctaBg: a.ctaBg || '#6366f1',
258 ctaColor: a.ctaColor || '#ffffff',
259 sliderColor: a.sliderColor || '#6366f1',
260 trackBg: a.trackBg || '#e5e7eb',
261 checkColor: a.checkColor || '#6366f1',
262 headingTypo: a.headingTypo || {},
263 subheadingTypo: a.subheadingTypo || {},
264 priceTypo: a.priceTypo || {},
265 ctaTypo: a.ctaTypo || {},
266 featureTypo: a.featureTypo || {}
267 };
268 return el('div', blockProps,
269 el('div', { className: 'bkbg-psl-app', 'data-opts': JSON.stringify(opts),
270 style: { background: a.sectionBg || '#f8fafc' } },
271 el('div', { className: 'bkbg-psl-header' },
272 el(RichText.Content, { tagName: 'h2', value: a.heading, className: 'bkbg-psl-heading',
273 style: { color: a.headingColor || '#1e1b4b' } }),
274 el(RichText.Content, { tagName: 'p', value: a.subheading, className: 'bkbg-psl-subheading' })
275 )
276 )
277 );
278 },
279
280 deprecated: [{
281 attributes: {
282 heading: { type: 'string', default: 'Simple, transparent pricing' },
283 subheading: { type: 'string', default: 'Scale up or down as your needs change.' },
284 showBilling: { type: 'boolean', default: true },
285 annualDiscount: { type: 'number', default: 20 },
286 initialTier: { type: 'number', default: 1 },
287 currency: { type: 'string', default: '$' },
288 period: { type: 'string', default: '/month' },
289 ctaText: { type: 'string', default: 'Get Started' },
290 tiers: { type: 'array', default: [] },
291 headingSize: { type: 'number', default: 36 },
292 subheadingSize: { type: 'number', default: 18 },
293 priceSize: { type: 'number', default: 56 },
294 cardRadius: { type: 'number', default: 24 },
295 sectionBg: { type: 'string', default: '#f8fafc' },
296 cardBg: { type: 'string', default: '#ffffff' },
297 headingColor: { type: 'string', default: '#1e1b4b' },
298 priceColor: { type: 'string', default: '#6366f1' },
299 featureColor: { type: 'string', default: '#374151' },
300 accentColor: { type: 'string', default: '#6366f1' },
301 ctaBg: { type: 'string', default: '#6366f1' },
302 ctaColor: { type: 'string', default: '#ffffff' },
303 sliderColor: { type: 'string', default: '#6366f1' },
304 trackBg: { type: 'string', default: '#e5e7eb' },
305 checkColor: { type: 'string', default: '#6366f1' },
306 ctaSize: { type: 'number', default: 16 },
307 headingFontWeight: { type: 'string', default: '800' },
308 subheadingFontWeight: { type: 'string', default: '400' },
309 priceFontWeight: { type: 'string', default: '700' }
310 },
311 save: function (props) {
312 var a = props.attributes;
313 var blockProps = useBlockProps.save();
314 var opts = {
315 tiers: a.tiers || [],
316 showBilling: a.showBilling !== false,
317 annualDiscount: a.annualDiscount || 20,
318 currency: a.currency || '$',
319 period: a.period || '/month',
320 ctaText: a.ctaText || 'Get Started',
321 priceSize: a.priceSize || 56,
322 cardRadius: a.cardRadius || 24,
323 sectionBg: a.sectionBg || '#f8fafc',
324 cardBg: a.cardBg || '#ffffff',
325 headingColor: a.headingColor || '#1e1b4b',
326 priceColor: a.priceColor || '#6366f1',
327 featureColor: a.featureColor || '#374151',
328 accentColor: a.accentColor || '#6366f1',
329 ctaBg: a.ctaBg || '#6366f1',
330 ctaColor: a.ctaColor || '#ffffff',
331 sliderColor: a.sliderColor || '#6366f1',
332 trackBg: a.trackBg || '#e5e7eb',
333 checkColor: a.checkColor || '#6366f1'
334 };
335 return el('div', blockProps,
336 el('div', { className: 'bkbg-psl-app', 'data-opts': JSON.stringify(opts),
337 style: { background: a.sectionBg || '#f8fafc' } },
338 el('div', { className: 'bkbg-psl-header' },
339 el(RichText.Content, { tagName: 'h2', value: a.heading, className: 'bkbg-psl-heading',
340 style: { color: a.headingColor || '#1e1b4b', fontSize: (a.headingSize || 36) + 'px' } }),
341 el(RichText.Content, { tagName: 'p', value: a.subheading, className: 'bkbg-psl-subheading',
342 style: { fontSize: (a.subheadingSize || 18) + 'px' } })
343 )
344 )
345 );
346 }
347 }]
348 });
349 }() );
350