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 / confetti-button / index.js

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

164 lines 11.2 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 Fragment = wp.element.Fragment;
4 var __ = wp.i18n.__;
5 var registerBlockType = wp.blocks.registerBlockType;
6 var InspectorControls = wp.blockEditor.InspectorControls;
7 var useBlockProps = wp.blockEditor.useBlockProps;
8 var PanelColorSettings = wp.blockEditor.PanelColorSettings;
9 var PanelBody = wp.components.PanelBody;
10 var TextControl = wp.components.TextControl;
11 var ToggleControl = wp.components.ToggleControl;
12 var RangeControl = wp.components.RangeControl;
13 var SelectControl = wp.components.SelectControl;
14
15 function getTypographyControl() {
16 return (typeof window.bkbgTypographyControl !== 'undefined') ? window.bkbgTypographyControl : null;
17 }
18 function getTypoCssVars() {
19 return (typeof window.bkbgTypoCssVars !== 'undefined') ? window.bkbgTypoCssVars : function () { return {}; };
20 }
21 function _tv(typoObj, prefix) { return getTypoCssVars()(typoObj || {}, prefix); }
22 var IP = function () { return window.bkbgIconPicker; };
23
24 var CONFETTI_STYLES = [
25 { label: '🎉 Burst (from button)', value: 'burst' },
26 { label: '🌧 Rain (from top)', value: 'rain' },
27 { label: '🎊 Sides (from left+right)', value: 'sides' },
28 { label: '🚀 Cannon (angled up)', value: 'cannon' },
29 { label: '🌀 Spiral', value: 'spiral' },
30 ];
31
32 var SHAPES = [
33 { label: 'Mixed (rectangles + circles)', value: 'mixed' },
34 { label: 'Rectangles only', value: 'rect' },
35 { label: 'Circles only', value: 'circle' },
36 { label: 'Stars', value: 'star' },
37 ];
38
39 var ALIGNS = [
40 { label: 'Left', value: 'left' },
41 { label: 'Center', value: 'center' },
42 { label: 'Right', value: 'right' },
43 ];
44
45 function ButtonPreview(props) {
46 var a = props.attributes;
47 var wrapStyle = {
48 textAlign: a.align || 'center',
49 padding: '24px',
50 };
51 var btnStyle = {
52 display: a.fullWidth ? 'block' : 'inline-flex',
53 alignItems: 'center',
54 justifyContent: 'center',
55 gap: '6px',
56 width: a.fullWidth ? '100%' : 'auto',
57 maxWidth: !a.fullWidth && a.maxWidth ? a.maxWidth + 'px' : undefined,
58 background: a.buttonBg,
59 color: a.buttonColor,
60 borderRadius: a.buttonRadius + 'px',
61 padding: a.buttonPaddingV + 'px ' + a.buttonPaddingH + 'px',
62 border: 'none',
63 cursor: 'pointer',
64 boxShadow: a.showShadow ? '0 8px 24px ' + a.buttonBg + '55, 0 4px 8px rgba(0,0,0,0.15)' : 'none',
65 lineHeight: 1.3,
66 transition: 'transform 0.15s, box-shadow 0.15s',
67 };
68 var beforeType = a.iconBeforeType || 'custom-char';
69 var afterType = a.iconAfterType || 'custom-char';
70 var hasBefore = beforeType !== 'custom-char' ? true : !!a.iconBefore;
71 var hasAfter = afterType !== 'custom-char' ? true : !!a.iconAfter;
72 return el('div', { style: wrapStyle },
73 el('button', { className: 'bkbg-cb-btn', style: btnStyle },
74 hasBefore && el('span', { className: 'bkbg-cb-icon-before' },
75 beforeType !== 'custom-char' ? IP().buildEditorIcon(beforeType, a.iconBefore, a.iconBeforeDashicon, a.iconBeforeImageUrl, a.iconBeforeDashiconColor) : a.iconBefore
76 ),
77 el('span', null, a.text || '🎉 Celebrate!'),
78 hasAfter && el('span', { className: 'bkbg-cb-icon-after' },
79 afterType !== 'custom-char' ? IP().buildEditorIcon(afterType, a.iconAfter, a.iconAfterDashicon, a.iconAfterImageUrl, a.iconAfterDashiconColor) : a.iconAfter
80 )
81 ),
82 a.showSubText && a.subText && el('p', { style: { marginTop: '8px', fontSize: '13px', color: '#64748b', opacity: 0.8 } }, a.subText)
83 );
84 }
85
86 registerBlockType('blockenberg/confetti-button', {
87 edit: function (props) {
88 var a = props.attributes;
89 var set = props.setAttributes;
90
91 return el(Fragment, null,
92 el(InspectorControls, null,
93 /* Button */
94 el(PanelBody, { title: 'Button Text', initialOpen: true },
95 el(TextControl, { __nextHasNoMarginBottom: true, label: 'Button label', value: a.text, onChange: function (v) { set({ text: v }); } }),
96 el('p', { style: { fontSize: '11px', fontWeight: 600, marginTop: '12px' } }, 'Icon before'),
97 el(IP().IconPickerControl, IP().iconPickerProps(a, set, { charAttr: 'iconBefore', typeAttr: 'iconBeforeType', dashiconAttr: 'iconBeforeDashicon', imageUrlAttr: 'iconBeforeImageUrl', colorAttr: 'iconBeforeDashiconColor' })),
98 el('p', { style: { fontSize: '11px', fontWeight: 600, marginTop: '12px' } }, 'Icon after'),
99 el(IP().IconPickerControl, IP().iconPickerProps(a, set, { charAttr: 'iconAfter', typeAttr: 'iconAfterType', dashiconAttr: 'iconAfterDashicon', imageUrlAttr: 'iconAfterImageUrl', colorAttr: 'iconAfterDashiconColor' })),
100 el(ToggleControl, { __nextHasNoMarginBottom: true, label: 'Show sub-text', checked: a.showSubText, onChange: function (v) { set({ showSubText: v }); } }),
101 a.showSubText && el(TextControl, { __nextHasNoMarginBottom: true, label: 'Sub-text', value: a.subText, onChange: function (v) { set({ subText: v }); } }),
102 ),
103 /* Link */
104 el(PanelBody, { title: 'Link', initialOpen: false },
105 el(TextControl, { __nextHasNoMarginBottom: true, label: 'URL (leave empty for click-only)', value: a.url, onChange: function (v) { set({ url: v }); } }),
106 el(ToggleControl, { __nextHasNoMarginBottom: true, label: 'Open in new tab', checked: a.openInNewTab, onChange: function (v) { set({ openInNewTab: v }); } }),
107 ),
108 /* Confetti */
109 el(PanelBody, { title: 'Confetti Settings', initialOpen: false },
110 el(SelectControl, { __nextHasNoMarginBottom: true, label: 'Confetti style', value: a.confettiStyle, options: CONFETTI_STYLES, onChange: function (v) { set({ confettiStyle: v }); } }),
111 el(SelectControl, { __nextHasNoMarginBottom: true, label: 'Particle shapes', value: a.shapes, options: SHAPES, onChange: function (v) { set({ shapes: v }); } }),
112 el(RangeControl, { __nextHasNoMarginBottom: true, label: 'Particle count', value: a.particleCount, min: 20, max: 500, step: 10, onChange: function (v) { set({ particleCount: v }); } }),
113 el(RangeControl, { __nextHasNoMarginBottom: true, label: 'Spread angle', value: a.spread, min: 10, max: 180, onChange: function (v) { set({ spread: v }); } }),
114 el(RangeControl, { __nextHasNoMarginBottom: true, label: 'Gravity', value: a.gravity, min: 0.1, max: 3, step: 0.1, onChange: function (v) { set({ gravity: v }); } }),
115 el(RangeControl, { __nextHasNoMarginBottom: true, label: 'Particle size (px)', value: a.particleSize, min: 4, max: 24, onChange: function (v) { set({ particleSize: v }); } }),
116 el(RangeControl, { __nextHasNoMarginBottom: true, label: 'Duration (ms)', value: a.duration, min: 500, max: 8000, step: 250, onChange: function (v) { set({ duration: v }); } }),
117 el(ToggleControl, { __nextHasNoMarginBottom: true, label: 'Allow repeat clicks', checked: a.repeat, onChange: function (v) { set({ repeat: v }); } }),
118 ),
119 /* Button Style */
120 el(PanelBody, { title: 'Button Style', initialOpen: false },
121 el(SelectControl, { __nextHasNoMarginBottom: true, label: 'Text alignment', value: a.align, options: ALIGNS, onChange: function (v) { set({ align: v }); } }),
122 el(ToggleControl, { __nextHasNoMarginBottom: true, label: 'Full width', checked: a.fullWidth, onChange: function (v) { set({ fullWidth: v }); } }),
123 !a.fullWidth && el(RangeControl, { __nextHasNoMarginBottom: true, label: 'Max width (px)', value: a.maxWidth, min: 100, max: 800, step: 10, onChange: function (v) { set({ maxWidth: v }); } }),
124 el(RangeControl, { __nextHasNoMarginBottom: true, label: 'Border radius (px)', value: a.buttonRadius, min: 0, max: 100, onChange: function (v) { set({ buttonRadius: v }); } }),
125 el(RangeControl, { __nextHasNoMarginBottom: true, label: 'Vertical padding (px)', value: a.buttonPaddingV, min: 4, max: 48, onChange: function (v) { set({ buttonPaddingV: v }); } }),
126 el(RangeControl, { __nextHasNoMarginBottom: true, label: 'Horizontal padding (px)', value: a.buttonPaddingH, min: 8, max: 120, onChange: function (v) { set({ buttonPaddingH: v }); } }),
127 el(ToggleControl, { __nextHasNoMarginBottom: true, label: 'Button shadow', checked: a.showShadow, onChange: function (v) { set({ showShadow: v }); } }),
128 ),
129
130 el( PanelBody, { title: __( 'Typography', 'blockenberg' ), initialOpen: false },
131 (function () {
132 var TC = getTypographyControl();
133 if (!TC) return el('p', { style: { color: '#999', fontSize: '12px', padding: '8px 0' } }, __('Typography control loading…', 'blockenberg'));
134 return el(TC, {
135 label: __('Button Text', 'blockenberg'),
136 value: a.typoButton || {},
137 onChange: function (v) { set({ typoButton: v }); }
138 });
139 })()
140 ),
141 el(PanelColorSettings, {
142 title: 'Button Colors',
143 initialOpen: false,
144 colorSettings: [
145 { value: a.buttonBg, onChange: function (v) { set({ buttonBg: v || '#6366f1' }); }, label: 'Button background' },
146 { value: a.buttonHoverBg, onChange: function (v) { set({ buttonHoverBg: v || '#4f46e5' }); }, label: 'Button hover background' },
147 { value: a.buttonColor, onChange: function (v) { set({ buttonColor: v || '#ffffff' }); }, label: 'Button text' },
148 ],
149 }),
150 ),
151 el('div', useBlockProps({ style: Object.assign({}, _tv(a.typoButton, '--bkcb-btn-')) }),
152 el(ButtonPreview, { attributes: a })
153 )
154 );
155 },
156 save: function (props) {
157 var a = props.attributes;
158 return el('div', useBlockProps.save({ style: Object.assign({}, _tv(a.typoButton, '--bkcb-btn-')) }),
159 el('div', { className: 'bkbg-cb-app', 'data-opts': JSON.stringify(a) })
160 );
161 },
162 });
163 }() );
164