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 / color-palette / index.js

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

375 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 __ = wp.i18n.__;
6 var registerBlockType = wp.blocks.registerBlockType;
7 var InspectorControls = wp.blockEditor.InspectorControls;
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 Button = wp.components.Button;
17 var ColorPicker = wp.components.ColorPicker;
18 var Popover = wp.components.Popover;
19
20 function getTypographyControl() {
21 return (window.bkbgTypographyControl || function () { return null; });
22 }
23
24 var _tv = (function () {
25 var fn = window.bkbgTypoCssVars;
26 return fn ? fn : function () { return {}; };
27 })();
28
29 /* ── helpers ────────────────────────────────────────────────────────────── */
30 function hexToRgb(hex) {
31 var r = 0, g = 0, b = 0;
32 var clean = hex ? hex.replace('#', '') : '000000';
33 if (clean.length === 3) { clean = clean.split('').map(function (c) { return c + c; }).join(''); }
34 r = parseInt(clean.substring(0, 2), 16);
35 g = parseInt(clean.substring(2, 4), 16);
36 b = parseInt(clean.substring(4, 6), 16);
37 return 'rgb(' + r + ', ' + g + ', ' + b + ')';
38 }
39
40 function sectionLabel(text) {
41 return el('p', {
42 style: { margin: '10px 0 4px', fontWeight: 600, fontSize: '11px', textTransform: 'uppercase', color: '#888', letterSpacing: '.5px' }
43 }, text);
44 }
45
46 /* ── colour swatch row ──────────────────────────────────────────────────── */
47 function ColorRow(props) {
48 var index = props.index;
49 var color = props.color;
50 var onChange = props.onChange;
51 var onRemove = props.onRemove;
52 var openKey = props.openKey;
53 var setOpenKey = props.setOpenKey;
54
55 var key = 'color-' + index;
56 var isOpen = openKey === key;
57
58 return el('div', { style: { background: '#f9fafb', borderRadius: '8px', padding: '10px', marginBottom: '8px', border: '1px solid #e5e7eb' } },
59 /* swatch preview */
60 el('div', { style: { display: 'flex', alignItems: 'center', gap: '10px', marginBottom: '8px' } },
61 el('button', {
62 type: 'button',
63 onClick: function () { setOpenKey(isOpen ? null : key); },
64 style: { width: '36px', height: '36px', borderRadius: '6px', border: '2px solid ' + (isOpen ? '#007cba' : '#ddd'), background: color.hex || '#ffffff', cursor: 'pointer', flexShrink: 0 }
65 }),
66 isOpen && el(Popover, { position: 'bottom left', onClose: function () { setOpenKey(null); } },
67 el('div', { style: { padding: '8px' }, onMouseDown: function (e) { e.stopPropagation(); } },
68 el(ColorPicker, {
69 color: color.hex,
70 enableAlpha: false,
71 onChange: function (v) { onChange('hex', v); }
72 })
73 )
74 ),
75 el('strong', { style: { fontSize: '13px', flex: 1 } }, color.name || __('Unnamed', 'blockenberg'))
76 ),
77 el(TextControl, { label: __('Name', 'blockenberg'), value: color.name || '', onChange: function (v) { onChange('name', v); } }),
78 el(TextControl, { label: __('CSS Variable', 'blockenberg'), value: color.cssVar || '', onChange: function (v) { onChange('cssVar', v); }, placeholder: '--color-primary' }),
79 el(Button, { isDestructive: true, isSmall: true, onClick: onRemove }, __('Remove', 'blockenberg'))
80 );
81 }
82
83 /* ── swatch card preview in editor ─────────────────────────────────────── */
84 function SwatchCard(props) {
85 var a = props.attrs;
86 var c = props.color;
87 var idx = props.index;
88
89 var cardStyle = {
90 borderRadius: a.borderRadius + 'px',
91 overflow: 'hidden',
92 background: a.labelBg,
93 boxShadow: a.showShadow ? '0 2px 12px rgba(0,0,0,0.1)' : 'none',
94 border: a.showBorder ? '1px solid ' + a.borderColor : 'none',
95 };
96
97 var swatchStyle = {
98 background: c.hex,
99 height: a.swatchHeight + 'px',
100 position: 'relative',
101 };
102
103 var labelStyle = {
104 padding: a.labelPadding + 'px',
105 textAlign: a.textAlign,
106 background: a.labelBg,
107 };
108
109 return el('div', { style: cardStyle },
110 el('div', { style: swatchStyle }),
111 el('div', { style: labelStyle },
112 a.showName && el('p', { className: 'bkcp-name', style: { margin: '0 0 2px', color: a.labelTextColor } }, c.name || ''),
113 a.showHex && el('p', { className: 'bkcp-hex', style: { margin: '0 0 2px', fontFamily: 'monospace', color: a.labelMeta } }, (c.hex || '').toUpperCase()),
114 a.showRGB && el('p', { className: 'bkcp-rgb', style: { margin: '0 0 2px', fontFamily: 'monospace', color: a.labelMeta } }, hexToRgb(c.hex)),
115 a.showCssVar && c.cssVar && el('p', { className: 'bkcp-cssvar', style: { margin: '0', fontFamily: 'monospace', color: a.labelMeta } }, c.cssVar),
116 a.showCopyBtn && el('button', {
117 type: 'button',
118 style: { marginTop: '6px', fontSize: '11px', padding: '3px 8px', borderRadius: '4px', border: '1px solid #e5e7eb', background: '#f3f4f6', cursor: 'pointer', color: '#374151' },
119 onClick: function (e) { e.preventDefault(); }
120 }, __('Copy', 'blockenberg'))
121 )
122 );
123 }
124
125 /* ── edit ───────────────────────────────────────────────────────────────── */
126 function Edit(props) {
127 var attributes = props.attributes;
128 var setAttributes = props.setAttributes;
129 var a = attributes;
130
131 var openKeyState = useState(null);
132 var openKey = openKeyState[0];
133 var setOpenKey = openKeyState[1];
134
135 function updateColor(idx, key, val) {
136 var next = (a.colors || []).slice();
137 next[idx] = Object.assign({}, next[idx], { [key]: val });
138 setAttributes({ colors: next });
139 }
140
141 function addColor() {
142 setAttributes({ colors: (a.colors || []).concat([{ name: 'New Color', hex: '#6c3fb5', cssVar: '' }]) });
143 }
144
145 function removeColor(idx) {
146 var next = (a.colors || []).slice();
147 next.splice(idx, 1);
148 setAttributes({ colors: next });
149 }
150
151 var bpStyle = { padding: '16px' };
152 Object.assign(bpStyle, _tv(a.typoTitle, '--bkbg-cp-tt'));
153 Object.assign(bpStyle, _tv(a.typoLabel, '--bkbg-cp-lb'));
154 var blockProps = useBlockProps({ style: bpStyle });
155
156 var gridStyle = {
157 display: 'grid',
158 gridTemplateColumns: 'repeat(' + a.columns + ', 1fr)',
159 gap: a.gap + 'px',
160 };
161
162 var listStyle = {
163 display: 'flex',
164 flexDirection: 'column',
165 gap: a.gap + 'px',
166 };
167
168 return el(Fragment, null,
169 el(InspectorControls, null,
170
171 /* Colors panel */
172
173 el( PanelBody, { title: __( 'Typography', 'blockenberg' ), initialOpen: false },
174 el(getTypographyControl(), { label: __('Title', 'blockenberg'), value: a.typoTitle, onChange: function (v) { setAttributes({ typoTitle: v }); } }),
175 el(getTypographyControl(), { label: __('Label', 'blockenberg'), value: a.typoLabel, onChange: function (v) { setAttributes({ typoLabel: v }); } })
176 ),
177 el(PanelBody, { title: __('Colors', 'blockenberg'), initialOpen: true },
178 (a.colors || []).map(function (color, idx) {
179 return el(ColorRow, {
180 key: idx,
181 index: idx,
182 color: color,
183 onChange: function (k, v) { updateColor(idx, k, v); },
184 onRemove: function () { removeColor(idx); },
185 openKey: openKey,
186 setOpenKey: setOpenKey,
187 });
188 }),
189 el(Button, { isPrimary: true, isSmall: true, onClick: addColor, style: { marginTop: '6px' } }, __('+ Add Color', 'blockenberg'))
190 ),
191
192 /* Layout panel */
193 el(PanelBody, { title: __('Layout', 'blockenberg'), initialOpen: false },
194 el(SelectControl, {
195 label: __('Display', 'blockenberg'),
196 value: a.layout,
197 options: [
198 { label: __('Grid', 'blockenberg'), value: 'grid' },
199 { label: __('List (horizontal)', 'blockenberg'), value: 'list' },
200 ],
201 onChange: function (v) { setAttributes({ layout: v }); }
202 }),
203 a.layout === 'grid' && el(RangeControl, {
204 label: __('Columns', 'blockenberg'),
205 value: a.columns,
206 min: 1,
207 max: 8,
208 onChange: function (v) { setAttributes({ columns: v }); }
209 }),
210 el(RangeControl, {
211 label: __('Swatch Height (px)', 'blockenberg'),
212 value: a.swatchHeight,
213 min: 40,
214 max: 300,
215 onChange: function (v) { setAttributes({ swatchHeight: v }); }
216 }),
217 el(RangeControl, {
218 label: __('Gap (px)', 'blockenberg'),
219 value: a.gap,
220 min: 0,
221 max: 48,
222 onChange: function (v) { setAttributes({ gap: v }); }
223 }),
224 el(RangeControl, {
225 label: __('Border Radius (px)', 'blockenberg'),
226 value: a.borderRadius,
227 min: 0,
228 max: 32,
229 onChange: function (v) { setAttributes({ borderRadius: v }); }
230 }),
231 el(RangeControl, {
232 label: __('Label Padding (px)', 'blockenberg'),
233 value: a.labelPadding,
234 min: 4,
235 max: 32,
236 onChange: function (v) { setAttributes({ labelPadding: v }); }
237 }),
238 el(SelectControl, {
239 label: __('Text Align', 'blockenberg'),
240 value: a.textAlign,
241 options: [
242 { label: __('Left', 'blockenberg'), value: 'left' },
243 { label: __('Center', 'blockenberg'), value: 'center' },
244 { label: __('Right', 'blockenberg'), value: 'right' },
245 ],
246 onChange: function (v) { setAttributes({ textAlign: v }); }
247 })
248 ),
249
250 /* Labels panel */
251 el(PanelBody, { title: __('Labels & Copy', 'blockenberg'), initialOpen: false },
252 el(ToggleControl, { label: __('Show Name', 'blockenberg'), checked: a.showName, onChange: function (v) { setAttributes({ showName: v }); }, __nextHasNoMarginBottom: true }),
253 el(ToggleControl, { label: __('Show Hex', 'blockenberg'), checked: a.showHex, onChange: function (v) { setAttributes({ showHex: v }); }, __nextHasNoMarginBottom: true }),
254 el(ToggleControl, { label: __('Show RGB', 'blockenberg'), checked: a.showRGB, onChange: function (v) { setAttributes({ showRGB: v }); }, __nextHasNoMarginBottom: true }),
255 el(ToggleControl, { label: __('Show CSS Variable', 'blockenberg'), checked: a.showCssVar, onChange: function (v) { setAttributes({ showCssVar: v }); }, __nextHasNoMarginBottom: true }),
256 el(ToggleControl, { label: __('Show Copy Button', 'blockenberg'), checked: a.showCopyBtn, onChange: function (v) { setAttributes({ showCopyBtn: v }); }, __nextHasNoMarginBottom: true }),
257 a.showCopyBtn && el(SelectControl, {
258 label: __('Copy Format', 'blockenberg'),
259 value: a.copyFormat,
260 options: [
261 { label: __('HEX', 'blockenberg'), value: 'hex' },
262 { label: __('RGB', 'blockenberg'), value: 'rgb' },
263 { label: __('CSS Variable', 'blockenberg'), value: 'css' },
264 ],
265 onChange: function (v) { setAttributes({ copyFormat: v }); }
266 }),
267 ),
268
269 /* Card style panel */
270 el(PanelBody, { title: __('Card Style', 'blockenberg'), initialOpen: false },
271 el(ToggleControl, { label: __('Show Shadow', 'blockenberg'), checked: a.showShadow, onChange: function (v) { setAttributes({ showShadow: v }); }, __nextHasNoMarginBottom: true }),
272 el(ToggleControl, { label: __('Show Border', 'blockenberg'), checked: a.showBorder, onChange: function (v) { setAttributes({ showBorder: v }); }, __nextHasNoMarginBottom: true })
273 ),
274
275 /* Title panel */
276 el(PanelBody, { title: __('Section Title', 'blockenberg'), initialOpen: false },
277 el(ToggleControl, { label: __('Show Title', 'blockenberg'), checked: a.showTitle, onChange: function (v) { setAttributes({ showTitle: v }); }, __nextHasNoMarginBottom: true }),
278 a.showTitle && el(Fragment, null,
279 el(TextControl, { label: __('Title text', 'blockenberg'), value: a.title, onChange: function (v) { setAttributes({ title: v }); } }),
280 el(RangeControl, { label: __('Title Size (px)', 'blockenberg'), value: a.titleSize, min: 14, max: 48, onChange: function (v) { setAttributes({ titleSize: v }); } })
281 )
282 ),
283
284 /* Colors */
285 el(PanelColorSettings, {
286 title: __('Colors', 'blockenberg'),
287 initialOpen: false,
288 colorSettings: [
289 { label: __('Card Background', 'blockenberg'), value: a.labelBg, onChange: function (v) { setAttributes({ labelBg: v || '#ffffff' }); } },
290 { label: __('Name Text', 'blockenberg'), value: a.labelTextColor, onChange: function (v) { setAttributes({ labelTextColor: v || '#1e1e1e' }); } },
291 { label: __('Meta Text (hex/rgb)', 'blockenberg'), value: a.labelMeta, onChange: function (v) { setAttributes({ labelMeta: v || '#6b7280' }); } },
292 { label: __('Border', 'blockenberg'), value: a.borderColor, onChange: function (v) { setAttributes({ borderColor: v || '#e5e7eb' }); } },
293 { label: __('Title', 'blockenberg'), value: a.titleColor, onChange: function (v) { setAttributes({ titleColor: v || '#1e1e1e' }); } },
294 ]
295 })
296 ),
297
298 /* ── editor preview ── */
299 el('div', blockProps,
300 a.showTitle && a.title && el('h3', { className: 'bkcp-title', style: { marginBottom: '16px', color: a.titleColor } }, a.title),
301 el('div', { style: a.layout === 'grid' ? gridStyle : listStyle },
302 (a.colors || []).map(function (color, idx) {
303 return el(SwatchCard, { key: idx, attrs: a, color: color, index: idx });
304 })
305 )
306 )
307 );
308 }
309
310 /* ── save ───────────────────────────────────────────────────────────────── */
311 function Save(props) {
312 var a = props.attributes;
313 var bpStyle = {};
314 Object.assign(bpStyle, _tv(a.typoTitle, '--bkbg-cp-tt'));
315 Object.assign(bpStyle, _tv(a.typoLabel, '--bkbg-cp-lb'));
316 var blockProps = wp.blockEditor.useBlockProps.save({ className: 'bkcp-wrap', style: bpStyle });
317
318 var gridStyle = a.layout === 'grid'
319 ? 'display:grid;grid-template-columns:repeat(' + a.columns + ',1fr);gap:' + a.gap + 'px;'
320 : 'display:flex;flex-wrap:wrap;gap:' + a.gap + 'px;';
321
322 return el('div', blockProps,
323 a.showTitle && a.title && el('h3', {
324 className: 'bkcp-title',
325 style: { marginBottom: '16px', color: a.titleColor }
326 }, a.title),
327 el('div', {
328 className: 'bkcp-grid',
329 style: { display: a.layout === 'grid' ? 'grid' : 'flex', gridTemplateColumns: a.layout === 'grid' ? ('repeat(' + a.columns + ',1fr)') : undefined, flexWrap: a.layout === 'list' ? 'wrap' : undefined, gap: a.gap + 'px' }
330 },
331 (a.colors || []).map(function (c, idx) {
332 return el('div', {
333 key: idx,
334 className: 'bkcp-card',
335 style: {
336 borderRadius: a.borderRadius + 'px',
337 overflow: 'hidden',
338 background: a.labelBg,
339 boxShadow: a.showShadow ? '0 2px 12px rgba(0,0,0,0.1)' : 'none',
340 border: a.showBorder ? '1px solid ' + a.borderColor : 'none',
341 }
342 },
343 el('div', {
344 className: 'bkcp-swatch',
345 style: { background: c.hex, height: a.swatchHeight + 'px' }
346 }),
347 el('div', {
348 className: 'bkcp-label',
349 style: { padding: a.labelPadding + 'px', textAlign: a.textAlign }
350 },
351 a.showName && el('p', { className: 'bkcp-name', style: { margin: '0 0 2px', color: a.labelTextColor } }, c.name || ''),
352 a.showHex && el('p', { className: 'bkcp-hex', style: { margin: '0 0 2px', fontFamily: 'monospace', color: a.labelMeta } }, (c.hex || '').toUpperCase()),
353 a.showRGB && el('p', { className: 'bkcp-rgb', style: { margin: '0 0 2px', fontFamily: 'monospace', color: a.labelMeta }, 'data-hex': c.hex }, ''),
354 a.showCssVar && c.cssVar && el('p', { className: 'bkcp-cssvar', style: { margin: '0', fontFamily: 'monospace', color: a.labelMeta } }, c.cssVar),
355 a.showCopyBtn && el('button', {
356 className: 'bkcp-copy',
357 type: 'button',
358 'data-hex': c.hex,
359 'data-rgb': '',
360 'data-cssvar': c.cssVar || '',
361 'data-format': a.copyFormat,
362 }, __('Copy', 'blockenberg'))
363 )
364 );
365 })
366 )
367 );
368 }
369
370 registerBlockType('blockenberg/color-palette', {
371 edit: Edit,
372 save: Save,
373 });
374 }() );
375