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 / tool-card / index.js

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

242 lines 17.0 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 InspectorControls = wp.blockEditor.InspectorControls;
6 var MediaUpload = wp.blockEditor.MediaUpload;
7 var MediaUploadCheck = wp.blockEditor.MediaUploadCheck;
8 var useBlockProps = wp.blockEditor.useBlockProps;
9 var RichText = wp.blockEditor.RichText;
10 var PanelColorSettings = wp.blockEditor.PanelColorSettings;
11 var PanelBody = wp.components.PanelBody;
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 TextareaControl = wp.components.TextareaControl;
17 var Button = wp.components.Button;
18
19 var _tc, _tvf;
20 Object.defineProperty(window, '_bkbgTypoCtrlCache', { get: function () { if (!_tc) { _tc = window.bkbgTypographyControl; } return _tc; } });
21 Object.defineProperty(window, '_bkbgTypoVarsCache', { get: function () { if (!_tvf) { _tvf = window.bkbgTypoCssVars; } return _tvf; } });
22 function getTypoControl(props, attrName, label) { return window._bkbgTypoCtrlCache(props, attrName, label); }
23
24 function HalfStar(color, key) {
25 return el('span', { key: key, style: { position: 'relative', display: 'inline-block', color: '#d1d5db', lineHeight: 1 } },
26 '�
27 ',
28 el('span', { style: { position: 'absolute', left: 0, top: 0, width: '50%', overflow: 'hidden', color: color } }, '�
29 ')
30 );
31 }
32
33 function StarRow(rating, starColor) {
34 var stars = [];
35 for (var i = 1; i <= 5; i++) {
36 if (rating >= i) {
37 stars.push(el('span', { key: i, style: { color: starColor, fontSize: '16px' } }, '�
38 '));
39 } else if (rating >= i - 0.5) {
40 stars.push(HalfStar(starColor, i));
41 } else {
42 stars.push(el('span', { key: i, style: { color: '#d1d5db', fontSize: '16px' } }, ''));
43 }
44 }
45 return el('span', {}, stars);
46 }
47
48 registerBlockType('blockenberg/tool-card', {
49 edit: function (props) {
50 var attr = props.attributes;
51 var set = props.setAttributes;
52
53 var blockProps = (function () {
54 var s = { background: '#f8fafc', padding: '24px' };
55 Object.assign(s, window._bkbgTypoVarsCache(attr.nameTypo, '--bktlc-nt-'), window._bkbgTypoVarsCache(attr.bodyTypo, '--bktlc-bt-'));
56 return useBlockProps({ style: s });
57 })();
58
59 /* Features list management */
60 function FeaturesList() {
61 return el('div', { style: { marginTop: '12px' } },
62 el('label', { style: { display: 'block', fontSize: '11px', fontWeight: 500, textTransform: 'uppercase', marginBottom: '8px', color: '#1e1e1e' } }, __('Key Features', 'blockenberg')),
63 (attr.features || []).map(function (f, idx) {
64 return el('div', { key: idx, style: { display: 'flex', gap: '6px', marginBottom: '6px' } },
65 el(TextControl, {
66 value: f, __nextHasNoMarginBottom: true,
67 onChange: function (v) {
68 var feats = attr.features.slice();
69 feats[idx] = v;
70 set({ features: feats });
71 }
72 }),
73 el(Button, {
74 variant: 'tertiary', isDestructive: true, style: { flexShrink: 0 },
75 onClick: function () { var feats = attr.features.filter(function (_, i) { return i !== idx; }); set({ features: feats }); }
76 }, '')
77 );
78 }),
79 el(Button, {
80 variant: 'secondary', __nextHasNoMarginBottom: true, style: { marginTop: '6px' },
81 onClick: function () { set({ features: (attr.features || []).concat(['New feature']) }); }
82 }, __('+ Add Feature', 'blockenberg'))
83 );
84 }
85
86 /* Card preview */
87 var isHorizontal = attr.layout === 'horizontal';
88 var cardStyle = {
89 display: 'flex', gap: '24px', flexDirection: isHorizontal ? 'row' : 'column',
90 background: attr.bgColor, border: '1px solid ' + attr.borderColor,
91 borderRadius: attr.borderRadius + 'px', padding: '28px', position: 'relative'
92 };
93
94 var logoSection = el('div', { style: { flexShrink: 0, display: 'flex', flexDirection: 'column', alignItems: 'center', gap: '12px', minWidth: isHorizontal ? '140px' : 'auto' } },
95 attr.logoUrl
96 ? el('img', { src: attr.logoUrl, alt: attr.logoAlt, style: { width: '72px', height: '72px', objectFit: 'contain', borderRadius: '12px', border: '1px solid ' + attr.borderColor } })
97 : el('div', { style: { width: '72px', height: '72px', borderRadius: '12px', background: attr.accentColor + '22', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: '32px' } }, '🔧'),
98 attr.showRating && el('div', { style: { textAlign: 'center' } },
99 StarRow(attr.rating, attr.starColor),
100 el('div', { style: { fontSize: '11px', color: attr.taglineColor, marginTop: '2px' } }, attr.ratingCount)
101 ),
102 attr.showPricing && el('div', { style: { fontSize: '11px', color: attr.pricingColor, textAlign: 'center', background: attr.bgColor === '#ffffff' ? '#f8fafc' : '#f0f0f0', borderRadius: '6px', padding: '4px 8px' } },
103 el('strong', { style: { textTransform: 'uppercase', fontSize: '10px', color: attr.accentColor } }, attr.pricing), el('br'),
104 attr.pricingNote
105 ),
106 el(Button, { variant: 'primary', style: { background: attr.ctaBg, color: attr.ctaColor, border: 'none', borderRadius: '6px', padding: '10px 18px', fontWeight: 600, width: '100%', justifyContent: 'center' } }, attr.ctaLabel)
107 );
108
109 var contentSection = el('div', { style: { flex: 1, minWidth: 0 } },
110 el('div', { style: { display: 'flex', alignItems: 'flex-start', gap: '10px', marginBottom: '6px' } },
111 el('h3', { className: 'bkbg-tlc-name', style: { margin: 0, color: attr.nameColor } }, attr.toolName),
112 attr.showBadge && attr.badgeText && el('span', { style: { background: attr.badgeBg, color: attr.badgeColor, fontSize: '11px', fontWeight: 700, padding: '3px 8px', borderRadius: '4px', whiteSpace: 'nowrap', flexShrink: 0 } }, attr.badgeText)
113 ),
114 el('p', { className: 'bkbg-tlc-tagline', style: { margin: '0 0 12px', color: attr.taglineColor } }, attr.tagline),
115 el('p', { className: 'bkbg-tlc-desc', style: { margin: '0 0 16px', color: attr.descColor } }, attr.description),
116 el('ul', { style: { margin: '0', paddingLeft: '0', listStyle: 'none' } },
117 (attr.features || []).slice(0, 5).map(function (f, i) {
118 return el('li', { key: i, style: { display: 'flex', alignItems: 'flex-start', gap: '8px', marginBottom: '6px', color: attr.featureColor } },
119 el('span', { style: { color: attr.accentColor, fontWeight: 700, flexShrink: 0 } }, ''),
120 f
121 );
122 })
123 )
124 );
125
126 var controls = el(InspectorControls, {},
127 el(PanelBody, { title: __('Tool Details', 'blockenberg'), initialOpen: true },
128 el(TextControl, { label: __('Tool Name', 'blockenberg'), value: attr.toolName, __nextHasNoMarginBottom: true, onChange: function (v) { set({ toolName: v }); } }),
129 el('div', { style: { marginTop: '12px' } },
130 el(TextControl, { label: __('Tagline', 'blockenberg'), value: attr.tagline, __nextHasNoMarginBottom: true, onChange: function (v) { set({ tagline: v }); } })
131 ),
132 el('div', { style: { marginTop: '12px' } },
133 el(TextareaControl, { label: __('Description', 'blockenberg'), value: attr.description, __nextHasNoMarginBottom: true, onChange: function (v) { set({ description: v }); } })
134 ),
135 FeaturesList()
136 ),
137 el(PanelBody, { title: __('Logo', 'blockenberg'), initialOpen: false },
138 el(MediaUploadCheck, {},
139 el(MediaUpload, {
140 onSelect: function (m) { set({ logoUrl: m.url, logoId: m.id, logoAlt: m.alt || '' }); },
141 allowedTypes: ['image'], value: attr.logoId,
142 render: function (rp) {
143 return el('div', {},
144 attr.logoUrl && el('img', { src: attr.logoUrl, style: { width: '72px', marginBottom: '8px', borderRadius: '8px' } }),
145 el(Button, { onClick: rp.open, variant: 'secondary', __nextHasNoMarginBottom: true }, attr.logoUrl ? __('Replace Logo', 'blockenberg') : __('Upload Logo', 'blockenberg')),
146 attr.logoUrl && el(Button, { onClick: function () { set({ logoUrl: '', logoId: 0, logoAlt: '' }); }, variant: 'link', isDestructive: true, style: { marginLeft: '8px' } }, __('Remove', 'blockenberg'))
147 );
148 }
149 })
150 )
151 ),
152 el(PanelBody, { title: __('Rating & Pricing', 'blockenberg'), initialOpen: false },
153 el(ToggleControl, { label: __('Show Rating', 'blockenberg'), checked: attr.showRating, __nextHasNoMarginBottom: true, onChange: function (v) { set({ showRating: v }); } }),
154 attr.showRating && el('div', { style: { marginTop: '12px' } },
155 el(RangeControl, { label: __('Rating (0-5)', 'blockenberg'), value: attr.rating, min: 0, max: 5, step: 0.5, __nextHasNoMarginBottom: true, onChange: function (v) { set({ rating: v }); } }),
156 el('div', { style: { marginTop: '8px' } },
157 el(TextControl, { label: __('Review Count Label', 'blockenberg'), value: attr.ratingCount, __nextHasNoMarginBottom: true, onChange: function (v) { set({ ratingCount: v }); } })
158 )
159 ),
160 el('div', { style: { marginTop: '12px' } },
161 el(ToggleControl, { label: __('Show Pricing', 'blockenberg'), checked: attr.showPricing, __nextHasNoMarginBottom: true, onChange: function (v) { set({ showPricing: v }); } })
162 ),
163 attr.showPricing && el('div', { style: { marginTop: '8px' } },
164 el(SelectControl, {
165 label: __('Pricing Model', 'blockenberg'), value: attr.pricing, __nextHasNoMarginBottom: true,
166 options: [{ label: 'Free', value: 'free' }, { label: 'Freemium', value: 'freemium' }, { label: 'Paid', value: 'paid' }],
167 onChange: function (v) { set({ pricing: v }); }
168 }),
169 el('div', { style: { marginTop: '8px' } },
170 el(TextControl, { label: __('Pricing Note', 'blockenberg'), value: attr.pricingNote, __nextHasNoMarginBottom: true, onChange: function (v) { set({ pricingNote: v }); } })
171 )
172 )
173 ),
174 el(PanelBody, { title: __('Badge & CTA', 'blockenberg'), initialOpen: false },
175 el(ToggleControl, { label: __('Show Badge', 'blockenberg'), checked: attr.showBadge, __nextHasNoMarginBottom: true, onChange: function (v) { set({ showBadge: v }); } }),
176 attr.showBadge && el('div', { style: { marginTop: '8px' } },
177 el(TextControl, { label: __('Badge Text', 'blockenberg'), value: attr.badgeText, __nextHasNoMarginBottom: true, onChange: function (v) { set({ badgeText: v }); } })
178 ),
179 el('div', { style: { marginTop: '12px' } },
180 el(TextControl, { label: __('CTA Label', 'blockenberg'), value: attr.ctaLabel, __nextHasNoMarginBottom: true, onChange: function (v) { set({ ctaLabel: v }); } })
181 ),
182 el('div', { style: { marginTop: '8px' } },
183 el(TextControl, { label: __('CTA URL', 'blockenberg'), value: attr.ctaUrl, __nextHasNoMarginBottom: true, onChange: function (v) { set({ ctaUrl: v }); } })
184 )
185 ),
186 el(PanelBody, { title: __('Layout', 'blockenberg'), initialOpen: false },
187 el(SelectControl, {
188 label: __('Layout', 'blockenberg'), value: attr.layout, __nextHasNoMarginBottom: true,
189 options: [{ label: 'Horizontal', value: 'horizontal' }, { label: 'Vertical', value: 'vertical' }, { label: 'Compact', value: 'compact' }],
190 onChange: function (v) { set({ layout: v }); }
191 }),
192 el('div', { style: { marginTop: '12px' } },
193 el(RangeControl, { label: __('Border Radius', 'blockenberg'), value: attr.borderRadius, min: 0, max: 32, __nextHasNoMarginBottom: true, onChange: function (v) { set({ borderRadius: v }); } })
194 )
195 ),
196 el(PanelBody, { title: __('Typography', 'blockenberg'), initialOpen: false },
197 getTypoControl(props, 'nameTypo', __('Tool Name', 'blockenberg')),
198 getTypoControl(props, 'bodyTypo', __('Body', 'blockenberg'))
199 ),
200 el(PanelColorSettings, {
201 title: __('Colors', 'blockenberg'), initialOpen: false,
202 colorSettings: [
203 { label: __('Card Background', 'blockenberg'), value: attr.bgColor, onChange: function (v) { set({ bgColor: v || '#ffffff' }); } },
204 { label: __('Card Border', 'blockenberg'), value: attr.borderColor, onChange: function (v) { set({ borderColor: v || '#e2e8f0' }); } },
205 { label: __('Accent', 'blockenberg'), value: attr.accentColor, onChange: function (v) { set({ accentColor: v || '#6366f1' }); } },
206 { label: __('Tool Name', 'blockenberg'), value: attr.nameColor, onChange: function (v) { set({ nameColor: v || '#111827' }); } },
207 { label: __('Tagline', 'blockenberg'), value: attr.taglineColor, onChange: function (v) { set({ taglineColor: v || '#6b7280' }); } },
208 { label: __('Description', 'blockenberg'), value: attr.descColor, onChange: function (v) { set({ descColor: v || '#374151' }); } },
209 { label: __('Feature Text', 'blockenberg'), value: attr.featureColor, onChange: function (v) { set({ featureColor: v || '#374151' }); } },
210 { label: __('Stars', 'blockenberg'), value: attr.starColor, onChange: function (v) { set({ starColor: v || '#f59e0b' }); } },
211 { label: __('Pricing Text', 'blockenberg'), value: attr.pricingColor, onChange: function (v) { set({ pricingColor: v || '#374151' }); } },
212 { label: __('Badge Background', 'blockenberg'), value: attr.badgeBg, onChange: function (v) { set({ badgeBg: v || '#fef3c7' }); } },
213 { label: __('Badge Text', 'blockenberg'), value: attr.badgeColor, onChange: function (v) { set({ badgeColor: v || '#92400e' }); } },
214 { label: __('CTA Button', 'blockenberg'), value: attr.ctaBg, onChange: function (v) { set({ ctaBg: v || '#6366f1' }); } },
215 { label: __('CTA Text', 'blockenberg'), value: attr.ctaColor, onChange: function (v) { set({ ctaColor: v || '#ffffff' }); } }
216 ]
217 })
218 );
219
220 return el('div', blockProps,
221 controls,
222 el('div', { className: 'bkbg-tlc-preview', style: cardStyle },
223 logoSection,
224 contentSection
225 )
226 );
227 },
228 save: function (props) {
229 var attr = props.attributes;
230 var useBlockProps = wp.blockEditor.useBlockProps;
231 var bp = (function () {
232 var tv = Object.assign({}, window._bkbgTypoVarsCache(attr.nameTypo, '--bktlc-nt-'), window._bkbgTypoVarsCache(attr.bodyTypo, '--bktlc-bt-'));
233 var parts = []; Object.keys(tv).forEach(function (k) { parts.push(k + ':' + tv[k]); });
234 return useBlockProps.save(parts.length ? { style: parts.join(';') } : {});
235 })();
236 return el('div', bp,
237 el('div', { className: 'bkbg-tlc-app', 'data-opts': JSON.stringify(attr) })
238 );
239 }
240 });
241 }() );
242