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 / parallax-section / index.js

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

237 lines 14.5 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 InnerBlocks = wp.blockEditor.InnerBlocks;
9 var MediaUpload = wp.blockEditor.MediaUpload;
10 var MediaUploadCheck = wp.blockEditor.MediaUploadCheck;
11 var PanelColorSettings = wp.blockEditor.PanelColorSettings;
12 var PanelBody = wp.components.PanelBody;
13 var ToggleControl = wp.components.ToggleControl;
14 var RangeControl = wp.components.RangeControl;
15 var SelectControl = wp.components.SelectControl;
16 var Button = wp.components.Button;
17
18 /* ── convert opacity 0-100 → hex alpha ────────────────────────────────── */
19 function hexAlpha(opacity) {
20 return Math.round(opacity / 100 * 255).toString(16).padStart(2, '0');
21 }
22
23 /* ── build section styles ─────────────────────────────────────────────── */
24 function buildSectionStyle(a) {
25 var style = {
26 position: 'relative',
27 overflow: 'hidden',
28 minHeight: a.minHeight + 'px',
29 borderRadius: a.borderRadius + 'px',
30 };
31 return style;
32 }
33
34 function buildBgStyle(a) {
35 var style = {
36 position: 'absolute',
37 inset: '-30% 0', /* extra room for parallax movement */
38 backgroundImage: a.bgImageUrl ? 'url(' + a.bgImageUrl + ')' : 'none',
39 backgroundColor: a.bgColor,
40 backgroundSize: a.bgSize,
41 backgroundPosition: a.bgPosition,
42 backgroundRepeat: a.bgRepeat,
43 backgroundAttachment: a.fixedBackground ? 'fixed' : 'scroll',
44 filter: a.bgBlur ? 'blur(' + a.bgBlur + 'px)' : 'none',
45 willChange: a.parallaxEnabled ? 'transform' : 'auto',
46 };
47 return style;
48 }
49
50 function buildOverlayStyle(a) {
51 var bg;
52 if (a.overlayGradient) {
53 var hex1 = (a.overlayGradientStart || '#000000') + hexAlpha(a.overlayOpacity);
54 bg = 'linear-gradient(' + a.overlayGradientDir + ', ' + hex1 + ', ' + (a.overlayGradientEnd || 'transparent') + ')';
55 } else {
56 bg = (a.overlayColor || '#000000') + hexAlpha(a.overlayOpacity);
57 }
58 return { position: 'absolute', inset: '0', background: bg, pointerEvents: 'none', zIndex: 1 };
59 }
60
61 function buildContentStyle(a) {
62 var justifyMap = { left: 'flex-start', center: 'center', right: 'flex-end' };
63 var alignMap = { top: 'flex-start', center: 'center', bottom: 'flex-end' };
64 return {
65 position: 'relative', zIndex: 2,
66 display: 'flex', flexDirection: 'column',
67 alignItems: justifyMap[a.contentAlign] || 'center',
68 justifyContent: alignMap[a.contentVAlign] || 'center',
69 minHeight: a.minHeight + 'px',
70 paddingTop: a.paddingTop + 'px',
71 paddingBottom: a.paddingBottom + 'px',
72 paddingLeft: a.paddingLeft + 'px',
73 paddingRight: a.paddingRight + 'px',
74 color: a.textColor,
75 };
76 }
77
78 registerBlockType('blockenberg/parallax-section', {
79 title: __('Parallax Section', 'blockenberg'),
80 icon: 'align-full-width',
81 category: 'bkbg-effects',
82 description: __('Section with a parallax-scrolling background image.', 'blockenberg'),
83
84 edit: function (props) {
85 var attributes = props.attributes;
86 var setAttributes = props.setAttributes;
87 var a = attributes;
88
89 var bgPosOptions = [
90 { label: 'Center Center', value: 'center center' },
91 { label: 'Top Center', value: 'top center' },
92 { label: 'Bottom Center', value: 'bottom center' },
93 { label: 'Center Left', value: 'center left' },
94 { label: 'Center Right', value: 'center right' },
95 ];
96 var bgSizeOptions = [
97 { label: 'Cover', value: 'cover' },
98 { label: 'Contain', value: 'contain' },
99 { label: 'Auto', value: 'auto' },
100 ];
101 var contentAlignOptions = [
102 { label: __('Left', 'blockenberg'), value: 'left' },
103 { label: __('Center', 'blockenberg'), value: 'center' },
104 { label: __('Right', 'blockenberg'), value: 'right' },
105 ];
106 var contentVAlignOptions = [
107 { label: __('Top', 'blockenberg'), value: 'top' },
108 { label: __('Middle', 'blockenberg'), value: 'center' },
109 { label: __('Bottom', 'blockenberg'), value: 'bottom' },
110 ];
111 var gradDirOptions = [
112 { label: 'Top → Bottom', value: 'to bottom' },
113 { label: 'Bottom → Top', value: 'to top' },
114 { label: 'Left → Right', value: 'to right' },
115 { label: 'Right → Left', value: 'to left' },
116 { label: 'Diagonal ↘', value: 'to bottom right' },
117 { label: 'Diagonal ↗', value: 'to top right' },
118 ];
119
120 var blockProps = useBlockProps({ className: 'bkps-outer', style: buildSectionStyle(a) });
121
122 return el(Fragment, null,
123 el(InspectorControls, null,
124
125 /* — Background — */
126 el(PanelBody, { title: __('Background Image', 'blockenberg'), initialOpen: true },
127 el(MediaUploadCheck, null,
128 el(MediaUpload, {
129 onSelect: function (media) {
130 setAttributes({ bgImageUrl: media.url, bgImageId: media.id, bgImageAlt: media.alt || '' });
131 },
132 allowedTypes: ['image'],
133 value: a.bgImageId,
134 render: function (ref) {
135 return el('div', null,
136 a.bgImageUrl && el('img', {
137 src: a.bgImageUrl, alt: a.bgImageAlt,
138 style: { width: '100%', height: '80px', objectFit: 'cover', borderRadius: '4px', marginBottom: '8px' }
139 }),
140 el(Button, { variant: a.bgImageUrl ? 'secondary' : 'primary', onClick: ref.open, style: { width: '100%', marginBottom: '4px' } },
141 a.bgImageUrl ? __('Replace Image', 'blockenberg') : __('Choose Image', 'blockenberg')
142 ),
143 a.bgImageUrl && el(Button, {
144 variant: 'tertiary', isDestructive: true, onClick: function () { setAttributes({ bgImageUrl: '', bgImageId: 0 }); }
145 }, __('Remove Image', 'blockenberg'))
146 );
147 }
148 })
149 ),
150 el(SelectControl, { label: __('Background Size', 'blockenberg'), value: a.bgSize, options: bgSizeOptions, onChange: function (v) { setAttributes({ bgSize: v }); } }),
151 el(SelectControl, { label: __('Background Position', 'blockenberg'), value: a.bgPosition, options: bgPosOptions, onChange: function (v) { setAttributes({ bgPosition: v }); } }),
152 el(RangeControl, { label: __('Background Blur (px)', 'blockenberg'), value: a.bgBlur, min: 0, max: 20, onChange: function (v) { setAttributes({ bgBlur: v }); } }),
153 el(ToggleControl, { label: __('Fixed Background (no parallax)', 'blockenberg'), checked: a.fixedBackground, onChange: function (v) { setAttributes({ fixedBackground: v }); }, __nextHasNoMarginBottom: true })
154 ),
155
156 /* — Parallax — */
157 el(PanelBody, { title: __('Parallax Effect', 'blockenberg'), initialOpen: false },
158 el(ToggleControl, { label: __('Enable Parallax', 'blockenberg'), checked: a.parallaxEnabled, onChange: function (v) { setAttributes({ parallaxEnabled: v }); }, __nextHasNoMarginBottom: true }),
159 a.parallaxEnabled && el(RangeControl, {
160 label: __('Parallax Speed', 'blockenberg'),
161 value: a.parallaxSpeed, min: 0.05, max: 0.9, step: 0.05,
162 help: __('0.05 = subtle · 0.5 = medium · 0.9 = strong', 'blockenberg'),
163 onChange: function (v) { setAttributes({ parallaxSpeed: v }); }
164 })
165 ),
166
167 /* — Overlay — */
168 el(PanelBody, { title: __('Overlay', 'blockenberg'), initialOpen: false },
169 el(RangeControl, { label: __('Overlay Opacity (%)', 'blockenberg'), value: a.overlayOpacity, min: 0, max: 100, onChange: function (v) { setAttributes({ overlayOpacity: v }); } }),
170 el(ToggleControl, { label: __('Gradient Overlay', 'blockenberg'), checked: a.overlayGradient, onChange: function (v) { setAttributes({ overlayGradient: v }); }, __nextHasNoMarginBottom: true }),
171 a.overlayGradient && el(SelectControl, { label: __('Direction', 'blockenberg'), value: a.overlayGradientDir, options: gradDirOptions, onChange: function (v) { setAttributes({ overlayGradientDir: v }); } })
172 ),
173
174 /* — Layout — */
175 el(PanelBody, { title: __('Layout', 'blockenberg'), initialOpen: false },
176 el(RangeControl, { label: __('Min Height (px)', 'blockenberg'), value: a.minHeight, min: 100, max: 1200, onChange: function (v) { setAttributes({ minHeight: v }); } }),
177 el(RangeControl, { label: __('Padding Top', 'blockenberg'), value: a.paddingTop, min: 0, max: 300, onChange: function (v) { setAttributes({ paddingTop: v }); } }),
178 el(RangeControl, { label: __('Padding Bottom', 'blockenberg'), value: a.paddingBottom, min: 0, max: 300, onChange: function (v) { setAttributes({ paddingBottom: v }); } }),
179 el(RangeControl, { label: __('Padding Left', 'blockenberg'), value: a.paddingLeft, min: 0, max: 200, onChange: function (v) { setAttributes({ paddingLeft: v }); } }),
180 el(RangeControl, { label: __('Padding Right', 'blockenberg'), value: a.paddingRight, min: 0, max: 200, onChange: function (v) { setAttributes({ paddingRight: v }); } }),
181 el(RangeControl, { label: __('Content Max Width (px)', 'blockenberg'), value: a.contentMaxWidth, min: 200, max: 1600, onChange: function (v) { setAttributes({ contentMaxWidth: v }); } }),
182 el(SelectControl, { label: __('Horizontal Align', 'blockenberg'), value: a.contentAlign, options: contentAlignOptions, onChange: function (v) { setAttributes({ contentAlign: v }); } }),
183 el(SelectControl, { label: __('Vertical Align', 'blockenberg'), value: a.contentVAlign, options: contentVAlignOptions, onChange: function (v) { setAttributes({ contentVAlign: v }); } }),
184 el(RangeControl, { label: __('Border Radius (px)', 'blockenberg'), value: a.borderRadius, min: 0, max: 80, onChange: function (v) { setAttributes({ borderRadius: v }); } })
185 ),
186
187 /* — Colors — */
188 el(PanelColorSettings, {
189 title: __('Colors', 'blockenberg'),
190 initialOpen: false,
191 colorSettings: [
192 { label: __('Background Fallback Color', 'blockenberg'), value: a.bgColor, onChange: function (v) { setAttributes({ bgColor: v || '#1e1e1e' }); } },
193 { label: __('Overlay Color', 'blockenberg'), value: a.overlayColor, onChange: function (v) { setAttributes({ overlayColor: v || '#000000' }); } },
194 { label: __('Overlay Gradient Start', 'blockenberg'), value: a.overlayGradientStart, onChange: function (v) { setAttributes({ overlayGradientStart: v || '#000000' }); } },
195 { label: __('Overlay Gradient End', 'blockenberg'), value: a.overlayGradientEnd, onChange: function (v) { setAttributes({ overlayGradientEnd: v || 'transparent' }); } },
196 { label: __('Content Text Color', 'blockenberg'), value: a.textColor, onChange: function (v) { setAttributes({ textColor: v || '#ffffff' }); } },
197 ]
198 })
199 ),
200
201 /* ── Canvas ─────────────────────────────────────────────────── */
202 el('div', blockProps,
203 /* background layer */
204 el('div', { className: 'bkps-bg', style: buildBgStyle(a) }),
205 /* overlay */
206 el('div', { className: 'bkps-overlay', style: buildOverlayStyle(a) }),
207 /* content */
208 el('div', { className: 'bkps-content', style: buildContentStyle(a) },
209 el('div', { style: { width: '100%', maxWidth: a.contentMaxWidth + 'px' } },
210 el(InnerBlocks, { templateLock: false })
211 )
212 )
213 )
214 );
215 },
216
217 save: function (props) {
218 var a = props.attributes;
219 var blockProps = wp.blockEditor.useBlockProps.save({ className: 'bkps-outer' });
220 return el('div', {
221 ...blockProps,
222 style: buildSectionStyle(a),
223 'data-parallax': a.parallaxEnabled && !a.fixedBackground ? '1' : '0',
224 'data-speed': a.parallaxSpeed,
225 },
226 el('div', { className: 'bkps-bg', style: buildBgStyle(a) }),
227 el('div', { className: 'bkps-overlay', style: buildOverlayStyle(a) }),
228 el('div', { className: 'bkps-content', style: buildContentStyle(a) },
229 el('div', { style: { width: '100%', maxWidth: a.contentMaxWidth + 'px' } },
230 el(InnerBlocks.Content, null)
231 )
232 )
233 );
234 }
235 });
236 }() );
237