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

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

191 lines 10.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 ( function () {
2 const el = window.wp.element.createElement;
3 const { registerBlockType } = window.wp.blocks;
4 const { InspectorControls, MediaUpload, MediaUploadCheck, PanelColorSettings } = window.wp.blockEditor;
5 const { PanelBody, RangeControl, SelectControl, TextControl, TextareaControl, ToggleControl, Button } = window.wp.components;
6 const { __ } = window.wp.i18n;
7
8 var _tc; function getTypoControl() { return _tc || (_tc = window.bkbgTypographyControl); }
9 var _tv; function getTypoCssVars() { return _tv || (_tv = window.bkbgTypoCssVars); }
10
11 function Stars( { count, color } ) {
12 return el( 'div', { className: 'bktg-stars' },
13 [1,2,3,4,5].map( n => el( 'span', { key: n, style: { color: n <= count ? color : '#ddd' } }, '�
14 ' ) )
15 );
16 }
17
18 function ItemEditor( { item, index, onChange, onRemove, showStars, starColor, showAvatar } ) {
19 function upd( key, val ) { onChange( index, Object.assign( {}, item, { [key]: val } ) ); }
20 return el( 'div', { style: { border: '1px solid #ddd', borderRadius: '8px', padding: '12px', marginBottom: '8px', background: '#fafafa' } },
21 el( TextareaControl, { label: __('Quote ') + (index+1), value: item.quote, onChange: v => upd('quote',v), rows: 3 } ),
22 el( TextControl, { label: __('Author'), value: item.author, onChange: v => upd('author',v) } ),
23 el( TextControl, { label: __('Role'), value: item.role, onChange: v => upd('role',v) } ),
24 showStars && el( RangeControl, { label: __('Stars'), value: item.stars, min: 1, max: 5, onChange: v => upd('stars',v) } ),
25 showAvatar && el( 'div', null,
26 item.avatarUrl
27 ? el( 'div', { style: { display:'flex', alignItems:'center', gap:'8px', marginBottom:'6px' } },
28 el( 'img', { src: item.avatarUrl, style: { width:48, height:48, borderRadius:'50%', objectFit:'cover' } } ),
29 el( Button, { isDestructive:true, isSmall:true, onClick: () => { upd('avatarUrl',''); upd('avatarId',0); } }, __('Remove') )
30 )
31 : el( MediaUploadCheck, null,
32 el( MediaUpload, {
33 onSelect: m => { upd('avatarUrl', m.url); upd('avatarId', m.id); },
34 allowedTypes: ['image'], value: item.avatarId,
35 render: ({ open }) => el( Button, { onClick: open, isSmall:true, variant:'secondary' }, __('Upload Avatar') )
36 } )
37 )
38 ),
39 el( Button, { isDestructive: true, isSmall: true, onClick: () => onRemove(index) }, __('Remove') )
40 );
41 }
42
43 function renderCard( item, attr ) {
44 const cardStyle = {
45 background: attr.cardBg,
46 borderRadius: attr.borderRadius + 'px',
47 padding: attr.cardPadding + 'px',
48 boxShadow: attr.shadow ? '0 4px 24px rgba(0,0,0,0.08)' : 'none',
49 color: attr.textColor,
50 textAlign: attr.quoteAlign,
51 };
52 return el( 'div', { className: 'bktg-card', style: cardStyle },
53 el( 'div', { className: 'bktg-quote-mark', style: { color: attr.accentColor } }, '\u201C' ),
54 el( 'p', { className: 'bktg-quote', style: { color: attr.textColor } }, item.quote ),
55 attr.showStars && el( Stars, { count: item.stars, color: attr.starColor } ),
56 el( 'div', { className: 'bktg-author-row', style: { justifyContent: attr.quoteAlign === 'center' ? 'center' : 'flex-start' } },
57 attr.showAvatar && (
58 item.avatarUrl
59 ? el( 'img', { src: item.avatarUrl, alt: item.author, className: 'bktg-avatar', style: { borderColor: attr.accentColor } } )
60 : el( 'div', { className: 'bktg-avatar bktg-avatar-init', style: { background: attr.accentColor } },
61 el('span', null, (item.author||'A').charAt(0))
62 )
63 ),
64 el( 'div', null,
65 el( 'strong', { className: 'bktg-name', style: { color: attr.textColor } }, item.author ),
66 el( 'span', { className: 'bktg-role' }, item.role )
67 )
68 )
69 );
70 }
71
72 registerBlockType( 'blockenberg/testimonial-grid', {
73 edit: function ( props ) {
74 const { attributes: attr, setAttributes } = props;
75
76 function updateItem( idx, next ) { const items = attr.items.slice(); items[idx] = next; setAttributes({ items }); }
77 function removeItem( idx ) { setAttributes({ items: attr.items.filter((_,i) => i !== idx) }); }
78
79 const wrapStyle = (function () {
80 var _tvf = getTypoCssVars();
81 var s = {
82 '--bktg-cols': attr.columns,
83 '--bktg-gap': attr.gap + 'px',
84 background: attr.bgColor,
85 padding: '32px',
86 borderRadius: '12px',
87 };
88 if (_tvf) {
89 Object.assign(s, _tvf(attr.quoteTypo, '--bktg-qt-'));
90 Object.assign(s, _tvf(attr.nameTypo, '--bktg-nm-'));
91 }
92 return s;
93 })();
94
95 return el( 'div', { className: 'bktg-wrap', style: wrapStyle },
96
97 el( InspectorControls, null,
98 el( PanelBody, { title: __('Testimonials'), initialOpen: true },
99 attr.items.map( (item, i) => el( ItemEditor, { key: i, item, index: i, onChange: updateItem, onRemove: removeItem, showStars: attr.showStars, starColor: attr.starColor, showAvatar: attr.showAvatar } ) ),
100 el( Button, { variant:'secondary', onClick: () => setAttributes({ items: [...attr.items, { quote:'New testimonial.', author:'New Author', role:'Title', avatarUrl:'', avatarId:0, stars:5 }] }), style:{ width:'100%', justifyContent:'center', marginTop:'8px' } }, __('+ Add Testimonial') )
101 ),
102 el( PanelBody, { title: __('Layout'), initialOpen: false },
103 el( RangeControl, { label: __('Columns'), value: attr.columns, min: 1, max: 4, onChange: v => setAttributes({columns:v}) } ),
104 el( RangeControl, { label: __('Gap (px)'), value: attr.gap, min: 8, max: 60, onChange: v => setAttributes({gap:v}) } ),
105 el( SelectControl, { label: __('Quote Alignment'), value: attr.quoteAlign, options: [{label:'Left',value:'left'},{label:'Center',value:'center'}], onChange: v => setAttributes({quoteAlign:v}) } ),
106 el( ToggleControl, { label: __('Show Stars'), checked: attr.showStars, onChange: v => setAttributes({showStars:v}), __nextHasNoMarginBottom: true } ),
107 el( ToggleControl, { label: __('Show Avatars'), checked: attr.showAvatar, onChange: v => setAttributes({showAvatar:v}), __nextHasNoMarginBottom: true } ),
108 el( ToggleControl, { label: __('Card Shadow'), checked: attr.shadow, onChange: v => setAttributes({shadow:v}), __nextHasNoMarginBottom: true } )
109 ),
110 el( PanelBody, { title: __('Card Style'), initialOpen: false },
111 el( RangeControl, { label: __('Border Radius'), value: attr.borderRadius, min:0, max:40, onChange: v => setAttributes({borderRadius:v}) } ),
112 el( RangeControl, { label: __('Card Padding'), value: attr.cardPadding, min:12, max:80, onChange: v => setAttributes({cardPadding:v}) } ),
113 ),
114
115 el( PanelBody, { title: __( 'Typography', 'blockenberg' ), initialOpen: false },
116 getTypoControl()({ label: __('Quote', 'blockenberg'), value: attr.quoteTypo, onChange: v => setAttributes({quoteTypo:v}) }),
117 getTypoControl()({ label: __('Author Name', 'blockenberg'), value: attr.nameTypo, onChange: v => setAttributes({nameTypo:v}) })
118 ),
119 el( PanelColorSettings, {
120 title: __('Colors'), initialOpen: false,
121 colorSettings: [
122 { label: __('Wrapper Background'), value: attr.bgColor, onChange: v => setAttributes({bgColor: v||'#f8f7ff'}) },
123 { label: __('Card Background'), value: attr.cardBg, onChange: v => setAttributes({cardBg: v||'#ffffff'}) },
124 { label: __('Text Color'), value: attr.textColor, onChange: v => setAttributes({textColor: v||'#222222'}) },
125 { label: __('Accent / Quote Mark'), value: attr.accentColor, onChange: v => setAttributes({accentColor: v||'#6c3fb5'}) },
126 { label: __('Star Color'), value: attr.starColor, onChange: v => setAttributes({starColor: v||'#f5a623'}) },
127 ]
128 } )
129 ),
130
131 el( 'div', { className: 'bktg-grid' },
132 attr.items.map( (item, i) => el('div', {key:i, className:'bktg-grid-item'}, renderCard(item, attr)) )
133 )
134 );
135 },
136
137 save: function ( { attributes: attr } ) {
138 const wrapStyle = (function () {
139 var _tvf = getTypoCssVars();
140 var s = {
141 '--bktg-cols': attr.columns,
142 '--bktg-gap': attr.gap + 'px',
143 background: attr.bgColor,
144 };
145 if (_tvf) {
146 Object.assign(s, _tvf(attr.quoteTypo, '--bktg-qt-'));
147 Object.assign(s, _tvf(attr.nameTypo, '--bktg-nm-'));
148 }
149 return s;
150 })();
151 return el( 'div', { className: 'bktg-wrap', style: wrapStyle },
152 el( 'div', { className: 'bktg-grid' },
153 attr.items.map( (item, i) =>
154 el( 'div', { key: i, className: 'bktg-grid-item' },
155 el( 'div', {
156 className: 'bktg-card',
157 style: {
158 background: attr.cardBg,
159 borderRadius: attr.borderRadius + 'px',
160 padding: attr.cardPadding + 'px',
161 boxShadow: attr.shadow ? '0 4px 24px rgba(0,0,0,0.08)' : 'none',
162 textAlign: attr.quoteAlign,
163 color: attr.textColor,
164 }
165 },
166 el('div', { className: 'bktg-quote-mark', style: { color: attr.accentColor } }, '\u201C'),
167 el('p', { className: 'bktg-quote', style: { color: attr.textColor } }, item.quote),
168 attr.showStars && el( 'div', { className: 'bktg-stars' },
169 [1,2,3,4,5].map(n => el('span', {key:n, style:{color: n<=item.stars ? attr.starColor : '#ddd'}}, '�
170 '))
171 ),
172 el('div', { className: 'bktg-author-row' },
173 attr.showAvatar && (
174 item.avatarUrl
175 ? el('img', { src: item.avatarUrl, alt: item.author, className: 'bktg-avatar', style:{borderColor:attr.accentColor} })
176 : el('div', { className: 'bktg-avatar bktg-avatar-init', style:{background:attr.accentColor} }, el('span',null,(item.author||'A').charAt(0)))
177 ),
178 el('div', null,
179 el('strong', { className:'bktg-name', style:{color:attr.textColor} }, item.author),
180 el('span', { className:'bktg-role' }, item.role)
181 )
182 )
183 )
184 )
185 )
186 )
187 );
188 }
189 });
190 }() );
191