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 / bento-grid / index.js

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

264 lines 20.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 Fragment = wp.element.Fragment;
4 var useState = wp.element.useState;
5 var registerBlockType = wp.blocks.registerBlockType;
6 var __ = wp.i18n.__;
7 var InspectorControls = wp.blockEditor.InspectorControls;
8 var PanelColorSettings = wp.blockEditor.PanelColorSettings;
9 var useBlockProps = wp.blockEditor.useBlockProps;
10 var MediaUpload = wp.blockEditor.MediaUpload;
11 var MediaUploadCheck = wp.blockEditor.MediaUploadCheck;
12 var PanelBody = wp.components.PanelBody;
13 var RangeControl = wp.components.RangeControl;
14 var ToggleControl = wp.components.ToggleControl;
15 var TextControl = wp.components.TextControl;
16 var TextareaControl = wp.components.TextareaControl;
17 var SelectControl = wp.components.SelectControl;
18 var Button = wp.components.Button;
19 var Notice = wp.components.Notice;
20
21 function getTypographyControl() { return window.bkbgTypographyControl; }
22 function getTypoCssVars() { return window.bkbgTypoCssVars; }
23
24 var builtInIcons = {
25 star: el('svg', { width: 18, height: 18, viewBox: '0 0 24 24', fill: 'currentColor' }, el('path', { d: 'M12 2l3.09 6.26L22 9.27l-5 4.87L18.18 21 12 17.77 5.82 21 7 14.14 2 9.27l6.91-1.01L12 2z' })),
26 bolt: el('svg', { width: 18, height: 18, viewBox: '0 0 24 24', fill: 'currentColor' }, el('path', { d: 'M13 2L3 14h9l-1 8 10-12h-9l1-8z' })),
27 heart: el('svg', { width: 18, height: 18, viewBox: '0 0 24 24', fill: 'currentColor' }, el('path', { d: 'M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78L12 21.23l8.84-8.84a5.5 5.5 0 0 0 0-7.78z' })),
28 check: el('svg', { width: 18, height: 18, viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: 2 }, el('polyline', { points: '20 6 9 17 4 12' })),
29 };
30
31 var LAYOUT_OPTIONS = [
32 { label: 'Classic (1 large + 2 + 2)', value: 'classic' },
33 { label: 'Spotlight (1 large + 3 small)', value: 'spotlight' },
34 { label: 'Even 2×3 grid', value: 'even' },
35 ];
36
37 var SPAN_OPTIONS = [
38 { label: 'Large (2 col)', value: 'large' },
39 { label: 'Medium (1.5 col)', value: 'medium' },
40 { label: 'Small (1 col)', value: 'small' },
41 ];
42
43 var TYPE_OPTIONS = [
44 { label: 'Text + Button', value: 'text' },
45 { label: 'Statistic', value: 'stat' },
46 { label: 'Image + Overlay', value: 'image' },
47 ];
48
49 function makeId() { return 'c' + Math.random().toString(36).substr(2, 6); }
50
51 function renderCellContent(cell, attributes) {
52 var btnRadius = attributes.btnBorderRadius !== undefined ? attributes.btnBorderRadius : 8;
53 return el(Fragment, null,
54 cell.imageUrl && cell.type === 'image' && el('div', { style: { position: 'absolute', inset: 0, background: 'rgba(0,0,0,0.35)', borderRadius: 'inherit' } }),
55 el('div', { style: { position: 'relative', zIndex: 1 } },
56 cell.eyebrow && el('p', { className: 'bkbg-bento-eyebrow', style: { margin: '0 0 6px', opacity: 0.8 } }, cell.eyebrow),
57 cell.title && el('h3', { className: 'bkbg-bento-title', style: { margin: '0 0 8px', color: 'inherit' } }, cell.title),
58 cell.desc && cell.type !== 'stat' && el('p', { className: 'bkbg-bento-desc', style: { opacity: 0.85, margin: '0 0 12px' } }, cell.desc),
59 cell.showButton && cell.buttonLabel && el('a', { href: cell.buttonUrl || '#', className: 'bkbg-bento-btn', style: { display: 'inline-block', padding: '7px 16px', background: cell.accentColor || '#6c3fb5', color: '#fff', borderRadius: btnRadius + 'px' } }, cell.buttonLabel)
60 )
61 );
62 }
63
64 registerBlockType('blockenberg/bento-grid', {
65 edit: function (props) {
66 var attributes = props.attributes;
67 var setAttributes = props.setAttributes;
68 var cells = attributes.cells;
69 var layout = attributes.layout;
70
71 var _tv = getTypoCssVars();
72 var bpStyle = { paddingTop: attributes.paddingTop + 'px', paddingBottom: attributes.paddingBottom + 'px', backgroundColor: attributes.bgColor || undefined };
73 if (_tv) {
74 Object.assign(bpStyle, _tv(attributes.eyebrowTypo || {}, '--bkbg-bento-eyebrow-'));
75 Object.assign(bpStyle, _tv(attributes.titleTypo || {}, '--bkbg-bento-title-'));
76 Object.assign(bpStyle, _tv(attributes.descTypo || {}, '--bkbg-bento-desc-'));
77 }
78 var blockProps = useBlockProps({ style: bpStyle });
79
80 var gridStyle = {
81 display: 'grid',
82 gap: attributes.gap + 'px',
83 gridTemplateColumns: layout === 'even' ? 'repeat(3, 1fr)' : 'repeat(4, 1fr)',
84 gridAutoRows: 'minmax(' + attributes.minRowHeight + 'px, auto)',
85 };
86
87 function setCell(id, patch) {
88 setAttributes({ cells: cells.map(function (c) { return c.id === id ? Object.assign({}, c, patch) : c; }) });
89 }
90 function addCell() {
91 setAttributes({ cells: cells.concat([{ id: makeId(), span: 'small', type: 'text', eyebrow: 'New', title: 'New cell', desc: '', imageUrl: '', imageId: 0, accentColor: '#6c3fb5', bgColor: '#f5f0ff', textColor: '#111827', showButton: false, buttonLabel: 'Learn more', buttonUrl: '' }]) });
92 }
93 function removeCell(id) {
94 if (cells.length <= 1) return;
95 setAttributes({ cells: cells.filter(function (c) { return c.id !== id; }) });
96 }
97
98 function colSpanFor(span, isEven) {
99 if (isEven) return 1;
100 if (span === 'large') return 2;
101 if (span === 'medium') return 2;
102 return 1;
103 }
104 var isEven = layout === 'even';
105
106 return el(Fragment, null,
107 el(InspectorControls, null,
108 el(PanelBody, { title: __('Layout', 'blockenberg'), initialOpen: true },
109 el(SelectControl, { label: __('Grid Layout', 'blockenberg'), value: layout, options: LAYOUT_OPTIONS, onChange: function (v) { setAttributes({ layout: v }); } }),
110 el(RangeControl, { label: __('Gap (px)', 'blockenberg'), value: attributes.gap, min: 0, max: 48, onChange: function (v) { setAttributes({ gap: v }); } }),
111 el(RangeControl, { label: __('Cell border radius (px)', 'blockenberg'), value: attributes.borderRadius, min: 0, max: 48, onChange: function (v) { setAttributes({ borderRadius: v }); } }),
112 el(RangeControl, { label: __('Min row height (px)', 'blockenberg'), value: attributes.minRowHeight, min: 100, max: 500, onChange: function (v) { setAttributes({ minRowHeight: v }); } }),
113 el(ToggleControl, { label: __('Hover lift effect', 'blockenberg'), checked: attributes.hoverLift, onChange: function (v) { setAttributes({ hoverLift: v }); }, __nextHasNoMarginBottom: true }),
114 el(ToggleControl, { label: __('Animate in on scroll', 'blockenberg'), checked: attributes.animateIn, onChange: function (v) { setAttributes({ animateIn: v }); }, __nextHasNoMarginBottom: true })
115 ),
116 el(PanelBody, { title: __('Typography', 'blockenberg'), initialOpen: false },
117 (function () { var TC = getTypographyControl(); return TC ? el(TC, { label: __('Eyebrow', 'blockenberg'), value: attributes.eyebrowTypo || {}, onChange: function (v) { setAttributes({ eyebrowTypo: v }); } }) : null; })(),
118 (function () { var TC = getTypographyControl(); return TC ? el(TC, { label: __('Title', 'blockenberg'), value: attributes.titleTypo || {}, onChange: function (v) { setAttributes({ titleTypo: v }); } }) : null; })(),
119 (function () { var TC = getTypographyControl(); return TC ? el(TC, { label: __('Description', 'blockenberg'), value: attributes.descTypo || {}, onChange: function (v) { setAttributes({ descTypo: v }); } }) : null; })(),
120 el(RangeControl, { label: __('Button border radius (px)', 'blockenberg'), value: attributes.btnBorderRadius, min: 0, max: 50, onChange: function (v) { setAttributes({ btnBorderRadius: v }); } })
121 ),
122 el(PanelBody, { title: __('Spacing', 'blockenberg'), initialOpen: false },
123 el(RangeControl, { label: __('Padding top (px)', 'blockenberg'), value: attributes.paddingTop, min: 0, max: 200, onChange: function (v) { setAttributes({ paddingTop: v }); } }),
124 el(RangeControl, { label: __('Padding bottom (px)', 'blockenberg'), value: attributes.paddingBottom, min: 0, max: 200, onChange: function (v) { setAttributes({ paddingBottom: v }); } })
125 ),
126 el(PanelColorSettings, {
127 title: __('Section Background', 'blockenberg'),
128 initialOpen: false,
129 colorSettings: [{ value: attributes.bgColor, onChange: function (v) { setAttributes({ bgColor: v || '' }); }, label: __('Background', 'blockenberg') }]
130 }),
131 el(PanelBody, { title: __('Cells', 'blockenberg'), initialOpen: false },
132 cells.map(function (cell, idx) {
133 return el(PanelBody, { key: cell.id, title: (cell.title || __('Cell', 'blockenberg')) + ' #' + (idx + 1), initialOpen: false },
134 el(SelectControl, { label: __('Size', 'blockenberg'), value: cell.span, options: SPAN_OPTIONS, onChange: function (v) { setCell(cell.id, { span: v }); } }),
135 el(SelectControl, { label: __('Cell type', 'blockenberg'), value: cell.type, options: TYPE_OPTIONS, onChange: function (v) { setCell(cell.id, { type: v }); } }),
136 el(TextControl, { label: __('Eyebrow / label', 'blockenberg'), value: cell.eyebrow, onChange: function (v) { setCell(cell.id, { eyebrow: v }); } }),
137 el(TextControl, { label: __('Title / Value', 'blockenberg'), value: cell.title, onChange: function (v) { setCell(cell.id, { title: v }); } }),
138 el(TextareaControl, { label: __('Description', 'blockenberg'), value: cell.desc, rows: 2, onChange: function (v) { setCell(cell.id, { desc: v }); } }),
139 el(ToggleControl, { label: __('Show button', 'blockenberg'), checked: cell.showButton, onChange: function (v) { setCell(cell.id, { showButton: v }); }, __nextHasNoMarginBottom: true }),
140 cell.showButton && el(TextControl, { label: __('Button label', 'blockenberg'), value: cell.buttonLabel, onChange: function (v) { setCell(cell.id, { buttonLabel: v }); } }),
141 cell.showButton && el(TextControl, { label: __('Button URL', 'blockenberg'), value: cell.buttonUrl, type: 'url', onChange: function (v) { setCell(cell.id, { buttonUrl: v }); } }),
142 el('p', { style: { margin: '8px 0 4px', fontWeight: 600, fontSize: '11px', textTransform: 'uppercase', letterSpacing: '0.06em' } }, __('Image', 'blockenberg')),
143 el(MediaUploadCheck, null,
144 el(MediaUpload, {
145 onSelect: function (media) { setCell(cell.id, { imageUrl: media.url, imageId: media.id }); },
146 allowedTypes: ['image'],
147 value: cell.imageId,
148 render: function (ref) {
149 return el(Button, { onClick: ref.open, variant: 'secondary', size: 'compact', style: { marginBottom: '8px' } },
150 cell.imageUrl ? __('Change image', 'blockenberg') : __('Add image', 'blockenberg')
151 );
152 }
153 })
154 ),
155 cell.imageUrl && el(Button, { onClick: function () { setCell(cell.id, { imageUrl: '', imageId: 0 }); }, variant: 'tertiary', size: 'compact', isDestructive: true, style: { marginBottom: '8px', display: 'block' } }, __('Remove image', 'blockenberg')),
156 el(PanelColorSettings, {
157 title: __('Cell Colors', 'blockenberg'),
158 initialOpen: false,
159 colorSettings: [
160 { value: cell.bgColor, onChange: function (v) { setCell(cell.id, { bgColor: v || '' }); }, label: __('Background', 'blockenberg') },
161 { value: cell.textColor, onChange: function (v) { setCell(cell.id, { textColor: v || '' }); }, label: __('Text', 'blockenberg') },
162 { value: cell.accentColor, onChange: function (v) { setCell(cell.id, { accentColor: v || '' }); }, label: __('Accent / Button', 'blockenberg') },
163 ]
164 }),
165 el(Button, { onClick: function () { removeCell(cell.id); }, variant: 'tertiary', isDestructive: true, size: 'compact' }, __('Remove cell', 'blockenberg'))
166 );
167 }),
168 el(Button, { onClick: addCell, variant: 'primary', style: { marginTop: '8px' } }, __('+ Add Cell', 'blockenberg'))
169 )
170 ),
171 el('div', blockProps,
172 el('div', { className: 'bkbg-bento-grid', 'data-layout': layout, 'data-hover-lift': attributes.hoverLift ? '1' : '0', 'data-animate': attributes.animateIn ? '1' : '0', style: gridStyle },
173 cells.map(function (cell) {
174 var span = colSpanFor(cell.span, isEven);
175 var cellStyle = {
176 backgroundColor: cell.bgColor || '#f5f0ff',
177 color: cell.textColor || '#111827',
178 borderRadius: attributes.borderRadius + 'px',
179 padding: '2rem',
180 display: 'flex',
181 flexDirection: 'column',
182 justifyContent: cell.type === 'stat' ? 'center' : 'flex-end',
183 position: 'relative',
184 overflow: 'hidden',
185 gridColumn: 'span ' + span,
186 transition: 'transform 0.2s ease, box-shadow 0.2s ease',
187 };
188 if (cell.imageUrl) {
189 cellStyle.backgroundImage = 'url(' + cell.imageUrl + ')';
190 cellStyle.backgroundSize = 'cover';
191 cellStyle.backgroundPosition = 'center';
192 }
193 return el('div', {
194 key: cell.id,
195 className: 'bkbg-bento-cell bkbg-bento-cell--' + cell.span,
196 style: cellStyle
197 },
198 renderCellContent(cell, attributes)
199 );
200 })
201 )
202 )
203 );
204 },
205
206 save: function (props) {
207 var attributes = props.attributes;
208 var cells = attributes.cells;
209 var layout = attributes.layout;
210 var isEven = layout === 'even';
211
212 function colSpanFor(span) {
213 if (isEven) return 1;
214 if (span === 'large') return 2;
215 if (span === 'medium') return 2;
216 return 1;
217 }
218
219 var _tv = getTypoCssVars();
220 var saveStyle = { paddingTop: attributes.paddingTop + 'px', paddingBottom: attributes.paddingBottom + 'px', backgroundColor: attributes.bgColor || undefined };
221 if (_tv) {
222 Object.assign(saveStyle, _tv(attributes.eyebrowTypo || {}, '--bkbg-bento-eyebrow-'));
223 Object.assign(saveStyle, _tv(attributes.titleTypo || {}, '--bkbg-bento-title-'));
224 Object.assign(saveStyle, _tv(attributes.descTypo || {}, '--bkbg-bento-desc-'));
225 }
226 var blockProps = wp.blockEditor.useBlockProps.save({ className: 'bkbg-bento-grid-wrap', style: saveStyle });
227
228 return el('div', blockProps,
229 el('div', { className: 'bkbg-bento-grid', 'data-layout': layout, 'data-hover-lift': attributes.hoverLift ? '1' : '0', 'data-animate': attributes.animateIn ? '1' : '0', style: { display: 'grid', gap: attributes.gap + 'px', gridTemplateColumns: isEven ? 'repeat(3, 1fr)' : 'repeat(4, 1fr)', gridAutoRows: 'minmax(' + attributes.minRowHeight + 'px, auto)' } },
230 cells.map(function (cell) {
231 var span = colSpanFor(cell.span);
232 var cellStyle = {
233 backgroundColor: cell.bgColor || '#f5f0ff',
234 color: cell.textColor || '#111827',
235 borderRadius: attributes.borderRadius + 'px',
236 padding: '2rem',
237 display: 'flex',
238 flexDirection: 'column',
239 justifyContent: cell.type === 'stat' ? 'center' : 'flex-end',
240 position: 'relative',
241 overflow: 'hidden',
242 gridColumn: 'span ' + span,
243 };
244 if (cell.imageUrl) {
245 cellStyle.backgroundImage = 'url(' + cell.imageUrl + ')';
246 cellStyle.backgroundSize = 'cover';
247 cellStyle.backgroundPosition = 'center';
248 }
249 return el('div', { key: cell.id, className: 'bkbg-bento-cell bkbg-bento-cell--' + cell.span, style: cellStyle },
250 cell.imageUrl && cell.type === 'image' && el('div', { className: 'bkbg-bento-overlay', style: { position: 'absolute', inset: 0, background: 'rgba(0,0,0,0.35)' } }),
251 el('div', { className: 'bkbg-bento-content', style: { position: 'relative', zIndex: 1 } },
252 cell.eyebrow && el('p', { className: 'bkbg-bento-eyebrow', style: { margin: '0 0 6px', opacity: 0.8 } }, cell.eyebrow),
253 cell.title && el('h3', { className: 'bkbg-bento-title', style: { margin: '0 0 8px', color: 'inherit' } }, cell.title),
254 cell.desc && cell.type !== 'stat' && el('p', { className: 'bkbg-bento-desc', style: { opacity: 0.85, margin: '0 0 12px' } }, cell.desc),
255 cell.showButton && cell.buttonLabel && el('a', { href: cell.buttonUrl || '#', className: 'bkbg-bento-btn', style: { display: 'inline-block', padding: '7px 16px', background: cell.accentColor || '#6c3fb5', color: '#fff', borderRadius: attributes.btnBorderRadius + 'px' } }, cell.buttonLabel)
256 )
257 );
258 })
259 )
260 );
261 }
262 });
263 }());
264