PluginProbe
Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor / 2.0.11
Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor v2.0.11
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 / gradient-section / index.js

index.js in Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor 2.0.11, at blocks/gradient-section/index.js

220 lines 17.9 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 useState = wp.element.useState;
5 var __ = wp.i18n.__;
6 var registerBlockType = wp.blocks.registerBlockType;
7 var InspectorControls = wp.blockEditor.InspectorControls;
8 var RichText = wp.blockEditor.RichText;
9 var useBlockProps = wp.blockEditor.useBlockProps;
10 var PanelBody = wp.components.PanelBody;
11 var Button = wp.components.Button;
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 URLInput = wp.blockEditor.URLInput;
17 var ColorPicker = wp.components.ColorPicker;
18 var Popover = wp.components.Popover;
19
20 /* ── typography lazy-getters ── */
21 function _tc() { return window.bkbgTypographyControl || null; }
22 function _tv() { return window.bkbgTypoCssVars || function () { return {}; }; }
23
24 var BTN_STYLE_OPTIONS = [
25 { label: __('Filled', 'blockenberg'), value: 'filled' },
26 { label: __('Outline', 'blockenberg'), value: 'outline' },
27 { label: __('Ghost', 'blockenberg'), value: 'ghost' },
28 ];
29 var ALIGN_OPTIONS = [
30 { label: __('Center', 'blockenberg'), value: 'center' },
31 { label: __('Left', 'blockenberg'), value: 'left' },
32 { label: __('Right', 'blockenberg'), value: 'right' },
33 ];
34 var TAG_OPTIONS = [
35 { label: 'H1', value: 'h1' },
36 { label: 'H2', value: 'h2' },
37 { label: 'H3', value: 'h3' },
38 { label: 'H4', value: 'h4' },
39 ];
40
41 function makeId() { return 'gs' + Math.random().toString(36).substr(2, 5); }
42
43 function buildGradientCSS(gradient, angle) {
44 if (!gradient || !gradient.length) return 'linear-gradient(' + angle + 'deg, #6c3fb5, #3b82f6)';
45 var stops = gradient.map(function (g) { return g.color; }).join(', ');
46 return 'linear-gradient(' + angle + 'deg, ' + stops + ')';
47 }
48
49 function buildWrapStyle(a) {
50 var grad = buildGradientCSS(a.gradient, a.gradientAngle);
51 return Object.assign({
52 '--bkbg-gs-headline-color': a.headlineColor,
53 '--bkbg-gs-subtext-color': a.subtextColor,
54 '--bkbg-gs-badge-bg': a.badgeBg,
55 '--bkbg-gs-badge-color': a.badgeColor,
56 '--bkbg-gs-badge-r': a.badgeRadius + 'px',
57 '--bkbg-gs-btn-bg': a.btnBg,
58 '--bkbg-gs-btn-color': a.btnColor,
59 '--bkbg-gs-btn2-color': a.btn2Color,
60 '--bkbg-gs-btn2-border': a.btn2BorderColor,
61 '--bkbg-gs-btn-r': a.btnRadius + 'px',
62 '--bkbg-gs-gradient': grad,
63 '--bkbg-gs-angle': a.gradientAngle + 'deg',
64 '--bkbg-gs-anim-dur': a.animationDuration + 's',
65 '--bkbg-gs-btn-sz': a.btnSize + 'px',
66 '--bkbg-gs-min-height': a.minHeight + 'px',
67 background: grad,
68 paddingTop: a.paddingTop + 'px',
69 paddingBottom: a.paddingBottom + 'px',
70 }, _tv()(a.typoHeadline, '--bkbg-gs-hl-'), _tv()(a.typoSubtext, '--bkbg-gs-st-'), _tv()(a.typoBadge, '--bkbg-gs-bg-'));
71 }
72
73 function renderColorControl(key, label, value, onChange, openKey, setOpenKey) {
74 var isOpen = openKey === key;
75 return el('div', { key: key, style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '4px 0', gap: '8px' } },
76 el('span', { style: { fontSize: '12px', color: '#1e1e1e', flex: 1, lineHeight: 1.4 } }, label),
77 el('div', { style: { position: 'relative', flexShrink: 0 } },
78 el('button', { type: 'button', onClick: function () { setOpenKey(isOpen ? null : key); }, style: { width: '28px', height: '28px', borderRadius: '4px', border: isOpen ? '2px solid #007cba' : '2px solid #ddd', cursor: 'pointer', padding: 0, background: value || '#ccc' } }),
79 isOpen && el(Popover, { position: 'bottom left', onClose: function () { setOpenKey(null); } },
80 el('div', { style: { padding: '8px' } },
81 el(ColorPicker, { color: value, enableAlpha: true, onChange: onChange })
82 )
83 )
84 )
85 );
86 }
87
88 registerBlockType('blockenberg/gradient-section', {
89 title: __('Gradient Section', 'blockenberg'),
90 icon: 'art',
91 category: 'bkbg-layout',
92
93 edit: function (props) {
94 var a = props.attributes;
95 var setAttributes = props.setAttributes;
96
97 var openColorKeyState = useState(null);
98 var openColorKey = openColorKeyState[0];
99 var setOpenColorKey = openColorKeyState[1];
100
101 var blockProps = useBlockProps({ style: buildWrapStyle(a), className: 'bkbg-gs-wrapper' + (a.animate ? ' bkbg-gs--animate' : ''), 'data-animate': a.animate ? 'true' : undefined });
102
103 function cc(key, label, attrKey) {
104 return renderColorControl(key, label, a[attrKey], function (val) {
105 var upd = {}; upd[attrKey] = val; setAttributes(upd);
106 }, openColorKey, setOpenColorKey);
107 }
108
109 function updateGradientColor(id, color) {
110 setAttributes({ gradient: a.gradient.map(function (g) { if (g.id !== id) return g; return Object.assign({}, g, { color: color }); }) });
111 }
112
113 var headlineTag = a.headlineTag || 'h2';
114 var overlayStyle = a.overlay ? { position: 'absolute', inset: 0, background: a.overlayColor, pointerEvents: 'none', zIndex: 0 } : null;
115 var innerStyle = { position: 'relative', zIndex: 1, maxWidth: a.contentMaxWidth + 'px', margin: '0 auto', minHeight: a.minHeight + 'px', display: 'flex', flexDirection: 'column', alignItems: a.textAlign === 'center' ? 'center' : (a.textAlign === 'right' ? 'flex-end' : 'flex-start'), justifyContent: 'center', textAlign: a.textAlign, padding: '40px 24px', boxSizing: 'border-box' };
116
117 var btnBase = { display: 'inline-flex', alignItems: 'center', justifyContent: 'center', padding: '0 28px', height: (a.btnSize + 22) + 'px', borderRadius: a.btnRadius + 'px', fontSize: a.btnSize + 'px', fontWeight: 700, fontFamily: 'inherit', cursor: 'pointer', textDecoration: 'none', boxSizing: 'border-box', transition: 'opacity 0.2s' };
118 var btn1Style = Object.assign({}, btnBase, { background: a.btnBg, color: a.btnColor, border: '2px solid transparent' });
119 var btn2Style = Object.assign({}, btnBase, { background: 'transparent', color: a.btn2Color, border: '2px solid ' + a.btn2BorderColor });
120
121 return el(Fragment, null,
122 el(InspectorControls, null,
123 el(PanelBody, { title: __('Gradient', 'blockenberg'), initialOpen: true },
124 el('p', { style: { fontSize: '12px', fontWeight: 600, margin: '0 0 6px' } }, __('Gradient colors', 'blockenberg')),
125 el('div', { style: { display: 'flex', flexWrap: 'wrap', gap: '8px', marginBottom: '12px' } },
126 a.gradient.map(function (g) {
127 var isOpenG = openColorKey === g.id;
128 return el('div', { key: g.id, style: { position: 'relative', display: 'flex', flexDirection: 'column', alignItems: 'center', gap: '4px' } },
129 el('button', { type: 'button', onClick: function () { setOpenColorKey(isOpenG ? null : g.id); }, style: { width: '36px', height: '36px', borderRadius: '50%', border: isOpenG ? '3px solid #007cba' : '2px solid #ddd', cursor: 'pointer', background: g.color, padding: 0 } }),
130 isOpenG && el(Popover, { position: 'bottom left', onClose: function () { setOpenColorKey(null); } },
131 el('div', { style: { padding: '8px' } },
132 el(ColorPicker, { color: g.color, onChange: function (val) { updateGradientColor(g.id, val); } })
133 )
134 ),
135 a.gradient.length > 2 && el('button', { type: 'button', onClick: function () { setAttributes({ gradient: a.gradient.filter(function (x) { return x.id !== g.id; }) }); }, style: { fontSize: '10px', color: '#dc3535', background: 'none', border: 'none', cursor: 'pointer', padding: 0 } }, '')
136 );
137 }),
138 a.gradient.length < 5 && el('button', { type: 'button', onClick: function () { setAttributes({ gradient: a.gradient.concat([{ id: makeId(), color: '#ffffff' }]) }); }, style: { width: '36px', height: '36px', borderRadius: '50%', border: '2px dashed #ccc', background: 'none', cursor: 'pointer', fontSize: '20px', color: '#999', display: 'flex', alignItems: 'center', justifyContent: 'center' } }, '+')
139 ),
140 el(RangeControl, { label: __('Gradient angle (°)', 'blockenberg'), value: a.gradientAngle, min: 0, max: 360, onChange: function (v) { setAttributes({ gradientAngle: v }); } }),
141 el(ToggleControl, { label: __('Animate gradient', 'blockenberg'), checked: a.animate, onChange: function (v) { setAttributes({ animate: v }); }, __nextHasNoMarginBottom: true }),
142 a.animate && el(RangeControl, { label: __('Animation speed (s)', 'blockenberg'), value: a.animationDuration, min: 3, max: 20, onChange: function (v) { setAttributes({ animationDuration: v }); } }),
143 el(ToggleControl, { label: __('Overlay', 'blockenberg'), checked: a.overlay, onChange: function (v) { setAttributes({ overlay: v }); }, __nextHasNoMarginBottom: true }),
144 a.overlay && cc('overlayColor', __('Overlay color', 'blockenberg'), 'overlayColor')
145 ),
146 el(PanelBody, { title: __('Content', 'blockenberg'), initialOpen: false },
147 el(ToggleControl, { label: __('Show badge', 'blockenberg'), checked: a.showBadge, onChange: function (v) { setAttributes({ showBadge: v }); }, __nextHasNoMarginBottom: true }),
148 a.showBadge && el(TextControl, { label: __('Badge text', 'blockenberg'), value: a.badge, onChange: function (v) { setAttributes({ badge: v }); } }),
149 el(SelectControl, { label: __('Headline tag', 'blockenberg'), value: a.headlineTag, options: TAG_OPTIONS, onChange: function (v) { setAttributes({ headlineTag: v }); } }),
150 el(TextControl, { label: __('Button 1 label', 'blockenberg'), value: a.btnLabel, onChange: function (v) { setAttributes({ btnLabel: v }); } }),
151 el(TextControl, { label: __('Button 1 URL', 'blockenberg'), value: a.btnUrl, onChange: function (v) { setAttributes({ btnUrl: v }); } }),
152 el(SelectControl, { label: __('Button 1 style', 'blockenberg'), value: a.btnStyle, options: BTN_STYLE_OPTIONS, onChange: function (v) { setAttributes({ btnStyle: v }); } }),
153 el(ToggleControl, { label: __('Show second button', 'blockenberg'), checked: a.showSecondBtn, onChange: function (v) { setAttributes({ showSecondBtn: v }); }, __nextHasNoMarginBottom: true }),
154 a.showSecondBtn && el(TextControl, { label: __('Button 2 label', 'blockenberg'), value: a.btn2Label, onChange: function (v) { setAttributes({ btn2Label: v }); } }),
155 a.showSecondBtn && el(TextControl, { label: __('Button 2 URL', 'blockenberg'), value: a.btn2Url, onChange: function (v) { setAttributes({ btn2Url: v }); } })
156 ),
157 el(PanelBody, { title: __('Layout', 'blockenberg'), initialOpen: false },
158 el(SelectControl, { label: __('Text align', 'blockenberg'), value: a.textAlign, options: ALIGN_OPTIONS, onChange: function (v) { setAttributes({ textAlign: v }); } }),
159 el(RangeControl, { label: __('Min height (px)', 'blockenberg'), value: a.minHeight, min: 200, max: 900, onChange: function (v) { setAttributes({ minHeight: v }); } }),
160 el(RangeControl, { label: __('Content max width', 'blockenberg'), value: a.contentMaxWidth, min: 400, max: 1400, onChange: function (v) { setAttributes({ contentMaxWidth: v }); } }),
161 el(RangeControl, { label: __('Button radius (px)','blockenberg'), value: a.btnRadius, min: 0, max: 99, onChange: function (v) { setAttributes({ btnRadius: v }); } }),
162 el(RangeControl, { label: __('Badge radius (px)', 'blockenberg'), value: a.badgeRadius, min: 0, max: 99, onChange: function (v) { setAttributes({ badgeRadius: v }); } })
163 ),
164 el(PanelBody, { title: __('Typography', 'blockenberg'), initialOpen: false },
165 _tc() && el(_tc(), { label:__('Headline','blockenberg'), value:a.typoHeadline, onChange:function(v){ setAttributes({typoHeadline:v}); } }),
166 _tc() && el(_tc(), { label:__('Subtext','blockenberg'), value:a.typoSubtext, onChange:function(v){ setAttributes({typoSubtext:v}); } }),
167 _tc() && el(_tc(), { label:__('Badge','blockenberg'), value:a.typoBadge, onChange:function(v){ setAttributes({typoBadge:v}); } }),
168 el(RangeControl, { label: __('Button (px)', 'blockenberg'), value: a.btnSize, min: 13, max: 22, onChange: function (v) { setAttributes({ btnSize: v }); } })
169 ),
170 el(PanelBody, { title: __('Colors', 'blockenberg'), initialOpen: false },
171 cc('headlineColor', __('Headline', 'blockenberg'), 'headlineColor'),
172 cc('subtextColor', __('Subtext', 'blockenberg'), 'subtextColor'),
173 cc('badgeBg', __('Badge background', 'blockenberg'), 'badgeBg'),
174 cc('badgeColor', __('Badge text', 'blockenberg'), 'badgeColor'),
175 cc('btnBg', __('Button 1 bg', 'blockenberg'), 'btnBg'),
176 cc('btnColor', __('Button 1 text', 'blockenberg'), 'btnColor'),
177 cc('btn2Color', __('Button 2 text', 'blockenberg'), 'btn2Color'),
178 cc('btn2BorderColor', __('Button 2 border', 'blockenberg'), 'btn2BorderColor')
179 ),
180 el(PanelBody, { title: __('Spacing', 'blockenberg'), initialOpen: false },
181 el(RangeControl, { label: __('Padding top (px)', 'blockenberg'), value: a.paddingTop, min: 0, max: 200, onChange: function (v) { setAttributes({ paddingTop: v }); } }),
182 el(RangeControl, { label: __('Padding bottom (px)', 'blockenberg'), value: a.paddingBottom, min: 0, max: 200, onChange: function (v) { setAttributes({ paddingBottom: v }); } })
183 )
184 ),
185
186 el('div', blockProps,
187 a.overlay && el('div', { className: 'bkbg-gs-overlay', style: overlayStyle }),
188 el('div', { className: 'bkbg-gs-inner', style: innerStyle },
189 a.showBadge && el('span', { className: 'bkbg-gs-badge', style: { display: 'inline-flex', alignItems: 'center', padding: '6px 16px', borderRadius: a.badgeRadius + 'px', background: a.badgeBg, color: a.badgeColor, marginBottom: '20px', backdropFilter: 'blur(10px)' } }, a.badge),
190 el(RichText, { tagName: headlineTag, className: 'bkbg-gs-headline', value: a.headline, onChange: function (v) { setAttributes({ headline: v }); }, placeholder: __('Headline…', 'blockenberg'), style: { color: a.headlineColor, margin: '0 0 16px', maxWidth: '100%' } }),
191 el(RichText, { tagName: 'p', className: 'bkbg-gs-subtext', value: a.subtext, onChange: function (v) { setAttributes({ subtext: v }); }, placeholder: __('Subtext description…', 'blockenberg'), style: { color: a.subtextColor, margin: '0 0 32px', maxWidth: '580px' } }),
192 el('div', { className: 'bkbg-gs-actions', style: { display: 'flex', gap: '12px', flexWrap: 'wrap', justifyContent: a.textAlign === 'center' ? 'center' : (a.textAlign === 'right' ? 'flex-end' : 'flex-start') } },
193 a.btnLabel && el('span', { className: 'bkbg-gs-btn bkbg-gs-btn--primary', style: btn1Style }, a.btnLabel),
194 a.showSecondBtn && a.btn2Label && el('span', { className: 'bkbg-gs-btn bkbg-gs-btn--secondary', style: btn2Style }, a.btn2Label)
195 )
196 )
197 )
198 );
199 },
200
201 save: function (props) {
202 var a = props.attributes;
203 var wrapStyle = buildWrapStyle(a);
204 var headlineTag = a.headlineTag || 'h2';
205 return el('div', wp.blockEditor.useBlockProps.save({ className: 'bkbg-gs-wrapper' + (a.animate ? ' bkbg-gs--animate' : ''), style: wrapStyle, 'data-animate': a.animate ? 'true' : undefined }),
206 a.overlay && el('div', { className: 'bkbg-gs-overlay', 'aria-hidden': 'true' }),
207 el('div', { className: 'bkbg-gs-inner' },
208 a.showBadge && el('span', { className: 'bkbg-gs-badge' }, a.badge),
209 el(RichText.Content, { tagName: headlineTag, className: 'bkbg-gs-headline', value: a.headline }),
210 el(RichText.Content, { tagName: 'p', className: 'bkbg-gs-subtext', value: a.subtext }),
211 el('div', { className: 'bkbg-gs-actions' },
212 a.btnLabel && el('a', { href: a.btnUrl || '#', className: 'bkbg-gs-btn bkbg-gs-btn--primary bkbg-gs-btn--' + a.btnStyle }, a.btnLabel),
213 a.showSecondBtn && a.btn2Label && el('a', { href: a.btn2Url || '#', className: 'bkbg-gs-btn bkbg-gs-btn--secondary' }, a.btn2Label)
214 )
215 )
216 );
217 }
218 });
219 }() );
220