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 / interactive-gradient-mesh / index.js

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

244 lines 13.1 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 useBlockProps = wp.blockEditor.useBlockProps;
6 var InspectorControls = wp.blockEditor.InspectorControls;
7 var PanelColorSettings = wp.blockEditor.PanelColorSettings;
8 var PanelBody = wp.components.PanelBody;
9 var RangeControl = wp.components.RangeControl;
10 var ToggleControl = wp.components.ToggleControl;
11 var SelectControl = wp.components.SelectControl;
12 var TextControl = wp.components.TextControl;
13 var Button = wp.components.Button;
14 var ColorPicker = wp.components.ColorPicker;
15 var Popover = wp.components.Popover;
16 var useState = wp.element.useState;
17 var Fragment = wp.element.Fragment;
18
19 var _TypographyControl, _typoCssVars;
20 function getTypographyControl() { return _TypographyControl || (_TypographyControl = window.bkbgTypographyControl); }
21 function getTypoCssVars() { return _typoCssVars || (_typoCssVars = window.bkbgTypoCssVars); }
22
23 var BLEND_MODES = ['screen','multiply','lighten','overlay','color-dodge','hard-light'].map(function (v) {
24 return { label: v, value: v };
25 });
26
27 /* Color row for editing the mesh colors array */
28 function ColorRow(props) {
29 var colors = props.colors;
30 var onChange = props.onChange;
31 var st = useState(-1); var openIdx = st[0]; var setOpenIdx = st[1];
32
33 function update(idx, val) {
34 var next = colors.slice();
35 next[idx] = val;
36 onChange(next);
37 }
38 function addColor() { onChange(colors.concat(['#a855f7'])); }
39 function removeColor(idx) {
40 if (colors.length <= 2) return;
41 onChange(colors.filter(function (_, i) { return i !== idx; }));
42 }
43
44 return el('div', {},
45 el('p', { style: { margin: '0 0 6px', fontWeight: 600, fontSize: 12 } }, __('Mesh Colors')),
46 colors.map(function (c, idx) {
47 return el('div', { key: idx, style: { display: 'flex', gap: 6, marginBottom: 6, alignItems: 'center', position: 'relative' }},
48 el('button', { type: 'button',
49 style: { width: 36, height: 36, border: '1px solid #ccc', padding: 0, cursor: 'pointer', borderRadius: 4, background: c, flexShrink: 0 },
50 onClick: function () { setOpenIdx(openIdx === idx ? -1 : idx); }
51 }),
52 el('span', { style: { flex: 1, fontSize: '12px', fontFamily: 'monospace', color: '#555' } }, c),
53 colors.length > 2 && el(Button, { isDestructive: true, size: 'small',
54 onClick: function () { removeColor(idx); }
55 }, ''),
56 openIdx === idx && el(Popover, { onClose: function () { setOpenIdx(-1); } },
57 el('div', { style: { padding: '8px' } },
58 el(ColorPicker, { color: c, enableAlpha: true, onChange: function (v) { update(idx, v); } })
59 )
60 )
61 );
62 }),
63 el(Button, { variant: 'secondary', onClick: addColor,
64 style: { width: '100%', marginTop: 4 }
65 }, __('+ Add Color'))
66 );
67 }
68
69 registerBlockType('blockenberg/interactive-gradient-mesh', {
70 title: __('Interactive Gradient Mesh'),
71 icon: 'art',
72 category: 'bkbg-effects',
73
74 edit: function (props) {
75 var attr = props.attributes;
76 var setAttr = props.setAttributes;
77 var bp = useBlockProps((function () {
78 var s = {};
79 var _tv = getTypoCssVars();
80 Object.assign(s, _tv(attr.headingTypo, '--bkbg-igm-h-'));
81 Object.assign(s, _tv(attr.subheadingTypo, '--bkbg-igm-sh-'));
82 return { className: 'bkbg-igm-wrap', style: s };
83 })());
84
85 var inspector = el(InspectorControls, {},
86 /* Mesh */
87 el(PanelBody, { title: __('Mesh'), initialOpen: true },
88 el(ColorRow, { colors: attr.colors,
89 onChange: function (v) { setAttr({ colors: v }); }
90 }),
91 el(RangeControl, { label: __('Blob Count'), value: attr.blobCount,
92 min: 2, max: 10,
93 onChange: function (v) { setAttr({ blobCount: v }); },
94 __nextHasNoMarginBottom: true }),
95 el(RangeControl, { label: __('Blob Size (% of container)'), value: attr.blobSize,
96 min: 20, max: 100,
97 onChange: function (v) { setAttr({ blobSize: v }); },
98 __nextHasNoMarginBottom: true }),
99 el(RangeControl, { label: __('Blur Amount (px)'), value: attr.blurAmount,
100 min: 20, max: 200,
101 onChange: function (v) { setAttr({ blurAmount: v }); },
102 __nextHasNoMarginBottom: true }),
103 el(SelectControl, { label: __('Blend Mode'), value: attr.blendMode,
104 options: BLEND_MODES,
105 onChange: function (v) { setAttr({ blendMode: v }); },
106 __nextHasNoMarginBottom: true }),
107 el(RangeControl, { label: __('Mouse Influence (px)'), value: attr.mouseInfluence,
108 min: 0, max: 100,
109 onChange: function (v) { setAttr({ mouseInfluence: v }); },
110 __nextHasNoMarginBottom: true }),
111 el(ToggleControl, { label: __('Auto Animate'), checked: attr.autoAnimate,
112 onChange: function (v) { setAttr({ autoAnimate: v }); },
113 __nextHasNoMarginBottom: true }),
114 el(RangeControl, { label: __('Animate Speed'), value: attr.animateSpeed,
115 min: 0.1, max: 3, step: 0.1,
116 onChange: function (v) { setAttr({ animateSpeed: v }); },
117 __nextHasNoMarginBottom: true })
118 ),
119
120 /* Container */
121 el(PanelBody, { title: __('Container'), initialOpen: false },
122 el(RangeControl, { label: __('Height (px)'), value: attr.height,
123 min: 120, max: 900, step: 20,
124 onChange: function (v) { setAttr({ height: v }); },
125 __nextHasNoMarginBottom: true }),
126 el(RangeControl, { label: __('Base BG (pick via color panel)'), value: 0,
127 min: 0, max: 0, onChange: function () {},
128 __nextHasNoMarginBottom: true
129 })
130 ),
131
132 /* Content */
133 el(PanelBody, { title: __('Content Overlay'), initialOpen: false },
134 el(ToggleControl, { label: __('Show Content'), checked: attr.showContent,
135 onChange: function (v) { setAttr({ showContent: v }); },
136 __nextHasNoMarginBottom: true }),
137 el(TextControl, { label: __('Heading'), value: attr.heading,
138 onChange: function (v) { setAttr({ heading: v }); },
139 __nextHasNoMarginBottom: true }),
140 el(TextControl, { label: __('Subheading'), value: attr.subheading,
141 onChange: function (v) { setAttr({ subheading: v }); },
142 __nextHasNoMarginBottom: true }),
143 el(TextControl, { label: __('CTA Button Text'), value: attr.ctaText,
144 onChange: function (v) { setAttr({ ctaText: v }); },
145 __nextHasNoMarginBottom: true }),
146 el(TextControl, { label: __('CTA URL'), value: attr.ctaUrl,
147 onChange: function (v) { setAttr({ ctaUrl: v }); },
148 __nextHasNoMarginBottom: true }),
149 el(RangeControl, { label: __('CTA Radius (px)'), value: attr.ctaRadius,
150 min: 0, max: 100,
151 onChange: function (v) { setAttr({ ctaRadius: v }); },
152 __nextHasNoMarginBottom: true }),
153 el(SelectControl, { label: __('Content Align'), value: attr.contentAlign,
154 options: [
155 { label: 'Left', value: 'left' },
156 { label: 'Center', value: 'center' },
157 { label: 'Right', value: 'right' }
158 ],
159 onChange: function (v) { setAttr({ contentAlign: v }); },
160 __nextHasNoMarginBottom: true })
161 ),
162
163
164 el(PanelBody, { title: __('Typography', 'blockenberg'), initialOpen: false },
165 getTypographyControl() && el(getTypographyControl(), { label: __('Heading'), value: attr.headingTypo, onChange: function (v) { setAttr({ headingTypo: v }); } }),
166 getTypographyControl() && el(getTypographyControl(), { label: __('Subheading'), value: attr.subheadingTypo, onChange: function (v) { setAttr({ subheadingTypo: v }); } }),
167 el(RangeControl, { label: __('CTA Size (px)', 'blockenberg'), value: attr.ctaSize, min: 10, max: 24, __nextHasNoMarginBottom: true, onChange: function (v) { setAttr({ ctaSize: v }); } })
168 ),
169 el(PanelColorSettings, {
170 title: __('Colors'), initialOpen: false,
171 colorSettings: [
172 { label: __('Base BG'), value: attr.baseBg,
173 onChange: function (v) { setAttr({ baseBg: v || '#0f172a' }); } },
174 { label: __('Heading'), value: attr.headingColor,
175 onChange: function (v) { setAttr({ headingColor: v || '#ffffff' }); } },
176 { label: __('Subheading'), value: attr.subheadingColor,
177 onChange: function (v) { setAttr({ subheadingColor: v }); } },
178 { label: __('CTA BG'), value: attr.ctaBg,
179 onChange: function (v) { setAttr({ ctaBg: v || '#ffffff' }); } },
180 { label: __('CTA Text'), value: attr.ctaColor,
181 onChange: function (v) { setAttr({ ctaColor: v || '#0f172a' }); } }
182 ]
183 })
184 );
185
186 /* Editor preview */
187 var gradients = attr.colors.map(function (c, i) {
188 var pos = ((i / attr.colors.length) * 100);
189 var pos2 = (((i + 1) / attr.colors.length) * 100);
190 return 'radial-gradient(ellipse at ' + pos + '% ' + pos2 + '%, ' + c + ' 0%, transparent 70%)';
191 });
192
193 var previewBg = attr.baseBg + '; background-image: ' + gradients.join(', ');
194
195 return el(Fragment, {}, inspector,
196 el('div', bp,
197 el('div', {
198 style: {
199 height: attr.height + 'px',
200 background: attr.baseBg,
201 backgroundImage: gradients.join(', '),
202 position: 'relative',
203 display: 'flex',
204 alignItems: 'center',
205 justifyContent: attr.contentAlign === 'center' ? 'center' : attr.contentAlign === 'right' ? 'flex-end' : 'flex-start',
206 padding: '40px 48px'
207 }
208 },
209 attr.showContent && el('div', {
210 className: 'bkbg-igm-inner',
211 style: {
212 textAlign: attr.contentAlign,
213 position: 'relative', zIndex: 2
214 }
215 },
216 el('h2', { className: 'bkbg-igm-heading', style: {
217 color: attr.headingColor, margin: '0 0 16px'
218 }}, attr.heading),
219 el('p', { className: 'bkbg-igm-subheading', style: {
220 color: attr.subheadingColor, margin: '0 0 24px'
221 }}, attr.subheading),
222 attr.ctaText && el('a', { href: '#', style: {
223 display: 'inline-block',
224 background: attr.ctaBg, color: attr.ctaColor,
225 padding: '12px 28px',
226 borderRadius: attr.ctaRadius + 'px',
227 fontWeight: 700, textDecoration: 'none', fontSize: (attr.ctaSize || 15)
228 }}, attr.ctaText)
229 )
230 )
231 )
232 );
233 },
234
235 save: function (props) {
236 var attr = props.attributes;
237 var bp = useBlockProps.save();
238 return el('div', bp,
239 el('div', { className: 'bkbg-igm-app', 'data-opts': JSON.stringify(attr) })
240 );
241 }
242 });
243 }() );
244