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 / brand-kit / index.js

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

459 lines 33.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 Fragment = wp.element.Fragment;
4 var useState = wp.element.useState;
5 var __ = wp.i18n.__;
6
7 function getTypographyControl() {
8 return (window.bkbgTypographyControl || function () { return null; });
9 }
10
11 function _tv(typo, prefix) {
12 if (!typo) return {};
13 var s = {};
14 if (typo.family) s[prefix + 'font-family'] = "'" + typo.family + "', sans-serif";
15 if (typo.weight) s[prefix + 'font-weight'] = typo.weight;
16 if (typo.transform) s[prefix + 'text-transform'] = typo.transform;
17 if (typo.style) s[prefix + 'font-style'] = typo.style;
18 if (typo.decoration) s[prefix + 'text-decoration'] = typo.decoration;
19 var su = typo.sizeUnit || 'px';
20 if (typo.sizeDesktop !== '' && typo.sizeDesktop != null) s[prefix + 'font-size-d'] = typo.sizeDesktop + su;
21 if (typo.sizeTablet !== '' && typo.sizeTablet != null) s[prefix + 'font-size-t'] = typo.sizeTablet + su;
22 if (typo.sizeMobile !== '' && typo.sizeMobile != null) s[prefix + 'font-size-m'] = typo.sizeMobile + su;
23 var lhu = typo.lineHeightUnit || '';
24 if (typo.lineHeightDesktop !== '' && typo.lineHeightDesktop != null) s[prefix + 'line-height-d'] = typo.lineHeightDesktop + lhu;
25 if (typo.lineHeightTablet !== '' && typo.lineHeightTablet != null) s[prefix + 'line-height-t'] = typo.lineHeightTablet + lhu;
26 if (typo.lineHeightMobile !== '' && typo.lineHeightMobile != null) s[prefix + 'line-height-m'] = typo.lineHeightMobile + lhu;
27 var lsu = typo.letterSpacingUnit || 'px';
28 if (typo.letterSpacingDesktop !== '' && typo.letterSpacingDesktop != null) s[prefix + 'letter-spacing-d'] = typo.letterSpacingDesktop + lsu;
29 if (typo.letterSpacingTablet !== '' && typo.letterSpacingTablet != null) s[prefix + 'letter-spacing-t'] = typo.letterSpacingTablet + lsu;
30 if (typo.letterSpacingMobile !== '' && typo.letterSpacingMobile != null) s[prefix + 'letter-spacing-m'] = typo.letterSpacingMobile + lsu;
31 var wsu = typo.wordSpacingUnit || 'px';
32 if (typo.wordSpacingDesktop !== '' && typo.wordSpacingDesktop != null) s[prefix + 'word-spacing-d'] = typo.wordSpacingDesktop + wsu;
33 if (typo.wordSpacingTablet !== '' && typo.wordSpacingTablet != null) s[prefix + 'word-spacing-t'] = typo.wordSpacingTablet + wsu;
34 if (typo.wordSpacingMobile !== '' && typo.wordSpacingMobile != null) s[prefix + 'word-spacing-m'] = typo.wordSpacingMobile + wsu;
35 return s;
36 }
37
38 var registerBlockType = wp.blocks.registerBlockType;
39 var InspectorControls = wp.blockEditor.InspectorControls;
40 var MediaUpload = wp.blockEditor.MediaUpload;
41 var MediaUploadCheck = wp.blockEditor.MediaUploadCheck;
42 var useBlockProps = wp.blockEditor.useBlockProps;
43 var PanelColorSettings = wp.blockEditor.PanelColorSettings;
44 var PanelBody = wp.components.PanelBody;
45 var ToggleControl = wp.components.ToggleControl;
46 var RangeControl = wp.components.RangeControl;
47 var TextControl = wp.components.TextControl;
48 var Button = wp.components.Button;
49 var IP = function () { return window.bkbgIconPicker; };
50
51 function lightenHex(hex) {
52 // Returns a semi-transparent light version for text on dark swatches
53 return hex;
54 }
55
56 function isBright(hex) {
57 var r = parseInt(hex.slice(1, 3), 16);
58 var g = parseInt(hex.slice(3, 5), 16);
59 var b = parseInt(hex.slice(5, 7), 16);
60 return (r * 299 + g * 587 + b * 114) / 1000 > 180;
61 }
62
63 function hexToRgb(hex) {
64 var r = parseInt(hex.slice(1, 3), 16);
65 var g = parseInt(hex.slice(3, 5), 16);
66 var b = parseInt(hex.slice(5, 7), 16);
67 return r + ', ' + g + ', ' + b;
68 }
69
70 function updateItem(arr, idx, field, val) {
71 return arr.map(function (item, i) {
72 if (i !== idx) return item;
73 var p = {}; p[field] = val;
74 return Object.assign({}, item, p);
75 });
76 }
77
78 function SectionLabel(title, a) {
79 return el('div', { style: { marginBottom: 20 } },
80 el('span', {
81 style: {
82 display: 'inline-block',
83 fontSize: 11,
84 fontWeight: 700,
85 letterSpacing: '0.08em',
86 textTransform: 'uppercase',
87 padding: '4px 12px',
88 borderRadius: 999,
89 background: a.sectionLabelBg,
90 color: a.sectionLabelColor,
91 }
92 }, title)
93 );
94 }
95
96 registerBlockType('blockenberg/brand-kit', {
97 title: __('Brand Kit', 'blockenberg'),
98 icon: 'art',
99 category: 'bkbg-business',
100 description: __('Complete brand style guide: colour swatches, typography, logos, and brand values.', 'blockenberg'),
101
102 edit: function (props) {
103 var a = props.attributes;
104 var set = props.setAttributes;
105 var blockProps = useBlockProps({
106 style: Object.assign({ background: a.containerBg || '', padding: a.containerPadding + 'px 0' }, _tv(a.typoTitle, '--bkbg-bdk-title-'), _tv(a.typoBody, '--bkbg-bdk-body-'))
107 });
108
109 // ── Inspector panels ──────────────────────────────────────────
110
111 // Colors panel (colour swatches configuration)
112 function addColor() {
113 set({ colors: a.colors.concat([{ name: 'New Color', value: '#000000', isLight: false }]) });
114 }
115 function removeColor(i) {
116 if (a.colors.length <= 1) return;
117 set({ colors: a.colors.filter(function (_, idx) { return idx !== i; }) });
118 }
119
120 // Fonts
121 function addFont() {
122 set({ fonts: a.fonts.concat([{
123 name: 'New Font', familyName: 'Georgia', cssFamily: 'Georgia, serif',
124 headingText: 'The quick brown fox', bodyText: 'Sample body text goes here.',
125 weights: '400, 700', sourceUrl: ''
126 }]) });
127 }
128 function removeFont(i) {
129 if (a.fonts.length <= 1) return;
130 set({ fonts: a.fonts.filter(function (_, idx) { return idx !== i; }) });
131 }
132
133 // Logos
134 function addLogo() {
135 set({ logos: a.logos.concat([{ label: 'Logo Variant', imageUrl: '', imageId: 0, imageAlt: 'Logo', bgStyle: 'light', description: '' }]) });
136 }
137 function removeLogo(i) {
138 if (a.logos.length <= 1) return;
139 set({ logos: a.logos.filter(function (_, idx) { return idx !== i; }) });
140 }
141
142 // Values
143 function addValue() {
144 set({ values: a.values.concat([{ icon: '', iconType: 'custom-char', iconDashicon: '', iconImageUrl: '', title: 'New Value', description: 'Describe this brand value here.' }]) });
145 }
146 function removeValue(i) {
147 if (a.values.length <= 1) return;
148 set({ values: a.values.filter(function (_, idx) { return idx !== i; }) });
149 }
150
151 // ── Editor preview ────────────────────────────────────────────
152 var cardStyle = {
153 background: a.cardBg,
154 border: '1px solid ' + a.cardBorder,
155 borderRadius: a.cardRadius + 'px',
156 padding: a.cardPadding + 'px',
157 marginBottom: a.sectionGap + 'px',
158 };
159
160 return el(Fragment, null,
161 el(InspectorControls, null,
162 // Sections toggle
163 el(PanelBody, { title: 'Sections', initialOpen: true },
164 el(TextControl, { label: 'Main title', value: a.sectionTitle, onChange: function (v) { set({ sectionTitle: v }); }, __nextHasNoMarginBottom: true }),
165 el('div', { style: { height: 8 } }),
166 el(ToggleControl, { label: 'Show main title', checked: a.showTitle, onChange: function (v) { set({ showTitle: v }); }, __nextHasNoMarginBottom: true }),
167 el('div', { style: { height: 8 } }),
168 el(ToggleControl, { label: 'Show Colour Palette', checked: a.showColors, onChange: function (v) { set({ showColors: v }); }, __nextHasNoMarginBottom: true }),
169 el('div', { style: { height: 8 } }),
170 el(ToggleControl, { label: 'Show Typography', checked: a.showTypography, onChange: function (v) { set({ showTypography: v }); }, __nextHasNoMarginBottom: true }),
171 el('div', { style: { height: 8 } }),
172 el(ToggleControl, { label: 'Show Logo Usage', checked: a.showLogos, onChange: function (v) { set({ showLogos: v }); }, __nextHasNoMarginBottom: true }),
173 el('div', { style: { height: 8 } }),
174 el(ToggleControl, { label: 'Show Brand Values', checked: a.showValues, onChange: function (v) { set({ showValues: v }); }, __nextHasNoMarginBottom: true })
175 ),
176
177 // Colour Swatches
178 el(PanelBody, { title: 'Colour Palette', initialOpen: false },
179 el(TextControl, { label: 'Section label', value: a.colorsTitle, onChange: function (v) { set({ colorsTitle: v }); }, __nextHasNoMarginBottom: true }),
180 el('div', { style: { height: 10 } }),
181 el(RangeControl, { label: 'Swatch height (px)', value: a.swatchHeight, min: 48, max: 160, onChange: function (v) { set({ swatchHeight: v }); }, __nextHasNoMarginBottom: true }),
182 el('div', { style: { height: 8 } }),
183 el(RangeControl, { label: 'Swatch radius (px)', value: a.swatchRadius, min: 0, max: 24, onChange: function (v) { set({ swatchRadius: v }); }, __nextHasNoMarginBottom: true }),
184 el('div', { style: { height: 8 } }),
185 el(ToggleControl, { label: 'Show colour name', checked: a.showColorName, onChange: function (v) { set({ showColorName: v }); }, __nextHasNoMarginBottom: true }),
186 el('div', { style: { height: 8 } }),
187 el(ToggleControl, { label: 'Show hex value', checked: a.showColorHex, onChange: function (v) { set({ showColorHex: v }); }, __nextHasNoMarginBottom: true }),
188 el('div', { style: { height: 8 } }),
189 el(ToggleControl, { label: 'Show copy hint', checked: a.showCopyHint, onChange: function (v) { set({ showCopyHint: v }); }, __nextHasNoMarginBottom: true }),
190 el('div', { style: { height: 12 } }),
191 el('div', { style: { fontWeight: 600, fontSize: 12, color: '#374151', marginBottom: 8 } }, 'Colours (' + a.colors.length + ')'),
192 a.colors.map(function (clr, i) {
193 return el('div', { key: i, style: { display: 'flex', gap: 8, alignItems: 'center', marginBottom: 8 } },
194 el('div', { style: { width: 24, height: 24, borderRadius: 4, background: clr.value, border: '1px solid #e5e7eb', flexShrink: 0 } }),
195 el(TextControl, { value: clr.name, onChange: function (v) { set({ colors: updateItem(a.colors, i, 'name', v) }); }, __nextHasNoMarginBottom: true, style: { flex: 1 } }),
196 el(TextControl, { value: clr.value, onChange: function (v) { set({ colors: updateItem(a.colors, i, 'value', v) }); }, __nextHasNoMarginBottom: true, style: { flex: 1 } }),
197 el(Button, { isDestructive: true, variant: 'tertiary', size: 'small', onClick: function () { removeColor(i); }, __nextHasNoMarginBottom: true }, '')
198 );
199 }),
200 el(Button, { variant: 'secondary', onClick: addColor, style: { width: '100%', justifyContent: 'center', marginTop: 4 }, __nextHasNoMarginBottom: true }, '+ Add Colour')
201 ),
202
203 // Typography
204 el(PanelBody, { title: 'Typography', initialOpen: false },
205 el(TextControl, { label: 'Section label', value: a.typographyTitle, onChange: function (v) { set({ typographyTitle: v }); }, __nextHasNoMarginBottom: true }),
206 el('div', { style: { height: 12 } }),
207 a.fonts.map(function (font, i) {
208 return el('div', { key: i, style: { border: '1px solid #e5e7eb', borderRadius: 8, padding: 10, marginBottom: 8 } },
209 el('div', { style: { display: 'flex', justifyContent: 'space-between', marginBottom: 8 } },
210 el('strong', { style: { fontSize: 12 } }, font.name),
211 el(Button, { isDestructive: true, variant: 'tertiary', size: 'small', onClick: function () { removeFont(i); }, __nextHasNoMarginBottom: true }, '')
212 ),
213 el(TextControl, { label: 'Label', value: font.name, onChange: function (v) { set({ fonts: updateItem(a.fonts, i, 'name', v) }); }, __nextHasNoMarginBottom: true }),
214 el('div', { style: { height: 6 } }),
215 el(TextControl, { label: 'Family name', value: font.familyName, onChange: function (v) { set({ fonts: updateItem(a.fonts, i, 'familyName', v) }); }, __nextHasNoMarginBottom: true }),
216 el('div', { style: { height: 6 } }),
217 el(TextControl, { label: 'CSS font-family', value: font.cssFamily, placeholder: "'Inter', sans-serif", onChange: function (v) { set({ fonts: updateItem(a.fonts, i, 'cssFamily', v) }); }, __nextHasNoMarginBottom: true }),
218 el('div', { style: { height: 6 } }),
219 el(TextControl, { label: 'Weights', value: font.weights, placeholder: '400, 600, 700', onChange: function (v) { set({ fonts: updateItem(a.fonts, i, 'weights', v) }); }, __nextHasNoMarginBottom: true }),
220 el('div', { style: { height: 6 } }),
221 el(TextControl, { label: 'Heading preview text', value: font.headingText, onChange: function (v) { set({ fonts: updateItem(a.fonts, i, 'headingText', v) }); }, __nextHasNoMarginBottom: true }),
222 el('div', { style: { height: 6 } }),
223 el(TextControl, { label: 'Body preview text', value: font.bodyText, onChange: function (v) { set({ fonts: updateItem(a.fonts, i, 'bodyText', v) }); }, __nextHasNoMarginBottom: true }),
224 el('div', { style: { height: 6 } }),
225 el(TextControl, { label: 'Source URL (optional)', value: font.sourceUrl, placeholder: 'https://fonts.google.com/...', onChange: function (v) { set({ fonts: updateItem(a.fonts, i, 'sourceUrl', v) }); }, __nextHasNoMarginBottom: true })
226 );
227 }),
228 el(Button, { variant: 'secondary', onClick: addFont, style: { width: '100%', justifyContent: 'center', marginTop: 4 }, __nextHasNoMarginBottom: true }, '+ Add Font')
229 ),
230
231 // Logos
232 el(PanelBody, { title: 'Logo Usage', initialOpen: false },
233 el(TextControl, { label: 'Section label', value: a.logosTitle, onChange: function (v) { set({ logosTitle: v }); }, __nextHasNoMarginBottom: true }),
234 el('div', { style: { height: 12 } }),
235 a.logos.map(function (logo, i) {
236 return el('div', { key: i, style: { border: '1px solid #e5e7eb', borderRadius: 8, padding: 10, marginBottom: 8 } },
237 el('div', { style: { display: 'flex', justifyContent: 'space-between', marginBottom: 8 } },
238 el('strong', { style: { fontSize: 12 } }, logo.label || 'Logo ' + (i + 1)),
239 el(Button, { isDestructive: true, variant: 'tertiary', size: 'small', onClick: function () { removeLogo(i); }, __nextHasNoMarginBottom: true }, '')
240 ),
241 el(TextControl, { label: 'Label', value: logo.label, onChange: function (v) { set({ logos: updateItem(a.logos, i, 'label', v) }); }, __nextHasNoMarginBottom: true }),
242 el('div', { style: { height: 6 } }),
243 el(TextControl, { label: 'Description', value: logo.description, onChange: function (v) { set({ logos: updateItem(a.logos, i, 'description', v) }); }, __nextHasNoMarginBottom: true }),
244 el('div', { style: { height: 8 } }),
245 el(MediaUploadCheck, null,
246 el(MediaUpload, {
247 onSelect: function (media) {
248 var updated = updateItem(a.logos, i, 'imageUrl', media.url);
249 updated = updateItem(updated, i, 'imageId', media.id);
250 updated = updateItem(updated, i, 'imageAlt', media.alt || '');
251 set({ logos: updated });
252 },
253 allowedTypes: ['image'],
254 value: logo.imageId,
255 render: function (ref) {
256 return el(Button, {
257 onClick: ref.open,
258 variant: logo.imageUrl ? 'secondary' : 'primary',
259 size: 'small',
260 __nextHasNoMarginBottom: true,
261 }, logo.imageUrl ? 'Change Logo' : 'Upload Logo');
262 }
263 })
264 )
265 );
266 }),
267 el(Button, { variant: 'secondary', onClick: addLogo, style: { width: '100%', justifyContent: 'center', marginTop: 4 }, __nextHasNoMarginBottom: true }, '+ Add Logo Variant')
268 ),
269
270 // Brand Values
271 el(PanelBody, { title: 'Brand Values', initialOpen: false },
272 el(TextControl, { label: 'Section label', value: a.valuesTitle, onChange: function (v) { set({ valuesTitle: v }); }, __nextHasNoMarginBottom: true }),
273 el('div', { style: { height: 12 } }),
274 a.values.map(function (val, i) {
275 return el('div', { key: i, style: { border: '1px solid #e5e7eb', borderRadius: 8, padding: 10, marginBottom: 8 } },
276 el('div', { style: { display: 'flex', justifyContent: 'space-between', marginBottom: 6 } },
277 el('strong', { style: { fontSize: 12 } }, val.icon + ' ' + val.title),
278 el(Button, { isDestructive: true, variant: 'tertiary', size: 'small', onClick: function () { removeValue(i); }, __nextHasNoMarginBottom: true }, '')
279 ),
280 el(IP().IconPickerControl, {
281 iconType: val.iconType, customChar: val.icon, dashicon: val.iconDashicon, imageUrl: val.iconImageUrl,
282 onChangeType: function (v) { set({ values: updateItem(a.values, i, 'iconType', v) }); },
283 onChangeChar: function (v) { set({ values: updateItem(a.values, i, 'icon', v) }); },
284 onChangeDashicon: function (v) { set({ values: updateItem(a.values, i, 'iconDashicon', v) }); },
285 onChangeImageUrl: function (v) { set({ values: updateItem(a.values, i, 'iconImageUrl', v) }); }
286 }),
287 el('div', { style: { height: 6 } }),
288 el(TextControl, { label: 'Title', value: val.title, onChange: function (v) { set({ values: updateItem(a.values, i, 'title', v) }); }, __nextHasNoMarginBottom: true }),
289 el('div', { style: { height: 6 } }),
290 el(TextControl, { label: 'Description', value: val.description, onChange: function (v) { set({ values: updateItem(a.values, i, 'description', v) }); }, __nextHasNoMarginBottom: true })
291 );
292 }),
293 el(Button, { variant: 'secondary', onClick: addValue, style: { width: '100%', justifyContent: 'center', marginTop: 4 }, __nextHasNoMarginBottom: true }, '+ Add Value')
294 ),
295
296 // Text Style
297 el(PanelBody, { title: __('Text Style', 'blockenberg'), initialOpen: false },
298 el(getTypographyControl(), { label: __('Main Title', 'blockenberg'), value: a.typoTitle, onChange: function (v) { set({ typoTitle: v }); } }),
299 el(getTypographyControl(), { label: __('Body Text', 'blockenberg'), value: a.typoBody, onChange: function (v) { set({ typoBody: v }); } })
300 ),
301
302 // Layout
303 el(PanelBody, { title: 'Layout', initialOpen: false },
304 el(RangeControl, { label: 'Max width (px)', value: a.maxWidth, min: 600, max: 1600, step: 50, onChange: function (v) { set({ maxWidth: v }); }, __nextHasNoMarginBottom: true }),
305 el('div', { style: { height: 10 } }),
306 el(RangeControl, { label: 'Container padding (px)', value: a.containerPadding, min: 0, max: 120, onChange: function (v) { set({ containerPadding: v }); }, __nextHasNoMarginBottom: true }),
307 el('div', { style: { height: 10 } }),
308 el(RangeControl, { label: 'Section gap (px)', value: a.sectionGap, min: 16, max: 120, onChange: function (v) { set({ sectionGap: v }); }, __nextHasNoMarginBottom: true }),
309 el('div', { style: { height: 10 } }),
310 el(RangeControl, { label: 'Card radius (px)', value: a.cardRadius, min: 0, max: 32, onChange: function (v) { set({ cardRadius: v }); }, __nextHasNoMarginBottom: true }),
311 el('div', { style: { height: 10 } }),
312 el(RangeControl, { label: 'Card padding (px)', value: a.cardPadding, min: 12, max: 64, onChange: function (v) { set({ cardPadding: v }); }, __nextHasNoMarginBottom: true })
313 ),
314
315 // Colors
316 el(PanelColorSettings, {
317 title: 'UI Colors',
318 initialOpen: false,
319 colorSettings: [
320 { label: 'Container Background', value: a.containerBg, onChange: function (v) { set({ containerBg: v || '' }); } },
321 { label: 'Card Background', value: a.cardBg, onChange: function (v) { set({ cardBg: v || '#ffffff' }); } },
322 { label: 'Card Border', value: a.cardBorder, onChange: function (v) { set({ cardBorder: v || '#e5e7eb' }); } },
323 { label: 'Heading Color', value: a.headingColor, onChange: function (v) { set({ headingColor: v || '#111827' }); } },
324 { label: 'Text Color', value: a.textColor, onChange: function (v) { set({ textColor: v || '#374151' }); } },
325 { label: 'Section Label Color', value: a.sectionLabelColor, onChange: function (v) { set({ sectionLabelColor: v || '#6366f1' }); } },
326 { label: 'Section Label Background', value: a.sectionLabelBg, onChange: function (v) { set({ sectionLabelBg: v || '#ede9fe' }); } },
327 { label: 'Value Icon Background', value: a.valueIconBg, onChange: function (v) { set({ valueIconBg: v || '#f5f3ff' }); } },
328 ]
329 })
330 ),
331
332 // ── Editor Preview ──
333 el('div', blockProps,
334 el('div', { style: { maxWidth: a.maxWidth + 'px', margin: '0 auto', padding: '0 24px' } },
335
336 // Main title
337 a.showTitle && el('h2', {
338 className: 'bkbg-bk-main-title',
339 style: { color: a.headingColor, marginBottom: a.sectionGap + 'px' }
340 }, a.sectionTitle),
341
342 // ── Colour palette ──
343 a.showColors && el('div', { style: cardStyle },
344 SectionLabel(a.colorsTitle, a),
345 el('div', {
346 style: { display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(110px, 1fr))', gap: 16 }
347 },
348 a.colors.map(function (clr, i) {
349 var bright = isBright(clr.value);
350 return el('div', { key: i },
351 el('div', {
352 style: {
353 height: a.swatchHeight + 'px',
354 background: clr.value,
355 borderRadius: a.swatchRadius + 'px',
356 border: bright ? '1px solid #e5e7eb' : 'none',
357 marginBottom: 8,
358 display: 'flex',
359 alignItems: 'flex-end',
360 justifyContent: 'flex-end',
361 padding: 8,
362 }
363 },
364 a.showCopyHint && el('span', {
365 style: { fontSize: 10, color: bright ? '#6b7280' : 'rgba(255,255,255,0.6)', background: bright ? 'rgba(0,0,0,0.06)' : 'rgba(0,0,0,0.2)', padding: '2px 6px', borderRadius: 4 }
366 }, 'copy')
367 ),
368 a.showColorName && el('div', { style: { fontSize: 12, fontWeight: 600, color: a.headingColor } }, clr.name),
369 a.showColorHex && el('div', { style: { fontSize: 11, color: a.textColor, fontFamily: 'monospace' } }, clr.value)
370 );
371 })
372 )
373 ),
374
375 // ── Typography ──
376 a.showTypography && el('div', { style: cardStyle },
377 SectionLabel(a.typographyTitle, a),
378 el('div', { style: { display: 'flex', flexDirection: 'column', gap: 32 } },
379 a.fonts.map(function (font, i) {
380 return el('div', { key: i, style: { paddingBottom: i < a.fonts.length - 1 ? 32 : 0, borderBottom: i < a.fonts.length - 1 ? '1px solid #f3f4f6' : 'none' } },
381 el('div', { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', marginBottom: 16 } },
382 el('div', null,
383 el('div', { style: { fontSize: 12, fontWeight: 700, textTransform: 'uppercase', letterSpacing: '0.06em', color: a.sectionLabelColor, marginBottom: 4 } }, font.name),
384 el('div', { style: { fontSize: 13, color: a.textColor } }, font.familyName + ' · ' + font.weights)
385 ),
386 font.sourceUrl && el('a', { href: font.sourceUrl, target: '_blank', style: { fontSize: 12, color: a.sectionLabelColor } }, 'View font →')
387 ),
388 el('div', { style: { fontFamily: font.cssFamily, fontSize: 36, fontWeight: 700, color: a.headingColor, marginBottom: 12, lineHeight: 1.2 } }, font.headingText),
389 el('div', { style: { fontFamily: font.cssFamily, fontSize: 16, color: a.textColor, lineHeight: 1.7 } }, font.bodyText)
390 );
391 })
392 )
393 ),
394
395 // ── Logos ──
396 a.showLogos && el('div', { style: cardStyle },
397 SectionLabel(a.logosTitle, a),
398 el('div', { style: { display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(220px, 1fr))', gap: 16 } },
399 a.logos.map(function (logo, i) {
400 var logoBg = logo.bgStyle === 'dark' ? '#0f172a' : logo.bgStyle === 'light' ? '#f8fafc' : 'transparent';
401 var checkered = logo.bgStyle === 'transparent';
402 return el('div', { key: i },
403 el('div', {
404 style: {
405 height: 120,
406 borderRadius: 8,
407 background: checkered ? 'repeating-conic-gradient(#e5e7eb 0% 25%, #fff 0% 50%) 0 / 20px 20px' : logoBg,
408 display: 'flex',
409 alignItems: 'center',
410 justifyContent: 'center',
411 marginBottom: 10,
412 border: '1px solid #e5e7eb',
413 overflow: 'hidden',
414 }
415 },
416 logo.imageUrl
417 ? el('img', { src: logo.imageUrl, alt: logo.imageAlt || '', style: { maxHeight: '80%', maxWidth: '80%', objectFit: 'contain' } })
418 : el('div', { style: { fontSize: 13, color: '#9ca3af' } }, '+ Upload logo')
419 ),
420 el('div', { style: { fontSize: 12, fontWeight: 600, color: a.headingColor, marginBottom: 2 } }, logo.label),
421 logo.description && el('div', { style: { fontSize: 11, color: a.textColor } }, logo.description)
422 );
423 })
424 )
425 ),
426
427 // ── Brand Values ──
428 a.showValues && el('div', { style: Object.assign({}, cardStyle, { marginBottom: 0 }) },
429 SectionLabel(a.valuesTitle, a),
430 el('div', { style: { display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(200px, 1fr))', gap: 20 } },
431 a.values.map(function (val, i) {
432 return el('div', { key: i, style: { display: 'flex', flexDirection: 'column', gap: 10 } },
433 el('div', {
434 style: {
435 width: 44, height: 44, borderRadius: 10,
436 background: a.valueIconBg,
437 display: 'flex', alignItems: 'center', justifyContent: 'center',
438 fontSize: 22,
439 }
440 }, (val.iconType || 'custom-char') !== 'custom-char' ? IP().buildEditorIcon(val.iconType, val.icon, val.iconDashicon, val.iconImageUrl, val.iconDashiconColor) : val.icon),
441 el('div', { className: 'bkbg-bk-value-title', style: { color: a.headingColor } }, val.title),
442 el('div', { className: 'bkbg-bk-value-desc', style: { color: a.textColor } }, val.description)
443 );
444 })
445 )
446 )
447 )
448 )
449 );
450 },
451
452 save: function (props) {
453 return el('div', useBlockProps.save(),
454 el('div', { className: 'bkbg-bk-app', 'data-opts': JSON.stringify(props.attributes) })
455 );
456 }
457 });
458 }() );
459