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 / contact-info / index.js

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

293 lines 16.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 (function () {
2 var el = window.wp.element.createElement;
3 var __ = function (s) { return s; };
4 var registerBlockType = window.wp.blocks.registerBlockType;
5 var InspectorControls = window.wp.blockEditor.InspectorControls;
6 var PanelBody = window.wp.components.PanelBody;
7 var PanelRow = window.wp.components.PanelRow;
8 var ToggleControl = window.wp.components.ToggleControl;
9 var SelectControl = window.wp.components.SelectControl;
10 var RangeControl = window.wp.components.RangeControl;
11 var TextControl = window.wp.components.TextControl;
12 var Button = window.wp.components.Button;
13 var PanelColorSettings = window.wp.blockEditor.PanelColorSettings;
14
15 function getTypographyControl() {
16 return (typeof window.bkbgTypographyControl !== 'undefined') ? window.bkbgTypographyControl : null;
17 }
18 function getTypoCssVars() {
19 return (typeof window.bkbgTypoCssVars !== 'undefined') ? window.bkbgTypoCssVars : function () { return {}; };
20 }
21 function _tv(typoObj, prefix) { return getTypoCssVars()(typoObj || {}, prefix); }
22
23 var TYPE_ICONS = {
24 address: '<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0 9.5A2.5 2.5 0 019.5 9 2.5 2.5 0 0112 6.5 2.5 2.5 0 0114.5 9 2.5 2.5 0 0112 11.5z"/></svg>',
25 phone: '<svg viewBox="0 0 24 24" fill="currentColor"><path d="M6.62 10.79a15.05 15.05 0 006.59 6.59l2.2-2.2a1 1 0 011.01-.24 11.4 11.4 0 003.57.57 1 1 0 011 1V20a1 1 0 01-1 1A17 17 0 013 4a1 1 0 011-1h3.5a1 1 0 011 1 11.4 11.4 0 00.57 3.57 1 1 0 01-.25 1.01l-2.2 2.21z"/></svg>',
26 email: '<svg viewBox="0 0 24 24" fill="currentColor"><path d="M20 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 4l-8 5-8-5V6l8 5 8-5v2z"/></svg>',
27 website: '<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 17.93c-3.95-.49-7-3.85-7-7.93 0-.62.08-1.21.21-1.79L9 15v1c0 1.1.9 2 2 2v1.93zm6.9-2.54A1.99 1.99 0 0016 14h-1v-3c0-.55-.45-1-1-1H8v-2h2c.55 0 1-.45 1-1V5.07c3.95.49 7 3.85 7 7.93 0 2.08-.8 3.97-2.1 5.39z"/></svg>',
28 hours: '<svg viewBox="0 0 24 24" fill="currentColor"><path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8zm.5-13H11v6l5.25 3.15.75-1.23-4.5-2.67V7z"/></svg>',
29 fax: '<svg viewBox="0 0 24 24" fill="currentColor"><path d="M17 2H7c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h10c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm0 18H7V4h10v16zM9 7h6v2H9zm0 4h6v2H9zm0 4h4v2H9z"/></svg>',
30 custom: '<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"/></svg>',
31 };
32
33 function generateId() {
34 return 'cti-' + Math.random().toString(36).slice(2, 9);
35 }
36
37 function updateItem(items, id, key, value, setA) {
38 var newItems = items.map(function (it) {
39 if (it.id !== id) return it;
40 var clone = Object.assign({}, it);
41 clone[key] = value;
42 return clone;
43 });
44 setA({ items: newItems });
45 }
46
47 function renderIcon(type, iconStyle, iconBg, iconColor, iconSize, boxSize, radius) {
48 var svgStr = TYPE_ICONS[type] || TYPE_ICONS.custom;
49 var noBox = iconStyle === 'none';
50 if (noBox) {
51 return el('span', {
52 className: 'bkbg-cti-icon bkbg-cti-icon--plain',
53 style: { color: iconColor, width: iconSize + 'px', height: iconSize + 'px', display: 'flex', flexShrink: 0 },
54 dangerouslySetInnerHTML: { __html: svgStr }
55 });
56 }
57 return el('span', {
58 className: 'bkbg-cti-icon bkbg-cti-icon--box',
59 style: {
60 background: iconBg,
61 color: iconColor,
62 width: boxSize + 'px',
63 height: boxSize + 'px',
64 borderRadius: radius + 'px',
65 display: 'flex',
66 alignItems: 'center',
67 justifyContent:'center',
68 flexShrink: 0,
69 padding: ((boxSize - iconSize) / 2) + 'px',
70 },
71 dangerouslySetInnerHTML: { __html: svgStr }
72 });
73 }
74
75 registerBlockType('blockenberg/contact-info', {
76 title: __('Contact Info'),
77 description: __('Display contact details with icons and optional schema markup.'),
78 category: 'bkbg-business',
79 icon: el('svg', { viewBox: '0 0 24 24', fill: 'currentColor', width: 24, height: 24 },
80 el('path', { d: 'M6.62 10.79a15.05 15.05 0 006.59 6.59l2.2-2.2a1 1 0 011.01-.24 11.4 11.4 0 003.57.57 1 1 0 011 1V20a1 1 0 01-1 1A17 17 0 013 4a1 1 0 011-1h3.5a1 1 0 011 1 11.4 11.4 0 00.57 3.57 1 1 0 01-.25 1.01l-2.2 2.21z' })
81 ),
82
83 edit: function (props) {
84 var a = props.attributes;
85 var setA = props.setAttributes;
86
87 var inspector = el(InspectorControls, null,
88 el(PanelBody, { title: __('Layout'), initialOpen: true },
89 el(SelectControl, {
90 label: __('Layout'), value: a.layout,
91 options: [
92 { label: 'Stacked (vertical)', value: 'stacked' },
93 { label: 'Inline (horizontal)', value: 'inline' },
94 { label: 'Grid', value: 'grid' },
95 ],
96 onChange: function (v) { setA({ layout: v }); },
97 }),
98 a.layout === 'grid' && el(RangeControl, {
99 label: __('Columns'), value: a.columns, min: 2, max: 4,
100 onChange: function (v) { setA({ columns: v }); },
101 }),
102 el(RangeControl, {
103 label: __('Item Spacing (px)'), value: a.itemSpacing, min: 8, max: 60,
104 onChange: function (v) { setA({ itemSpacing: v }); },
105 }),
106 el(ToggleControl, {
107 label: __('Show Labels'), checked: a.showLabel,
108 onChange: function (v) { setA({ showLabel: v }); },
109 __nextHasNoMarginBottom: true,
110 }),
111 el(ToggleControl, {
112 label: __('Inject Schema.org markup'), checked: a.schemaEnabled,
113 onChange: function (v) { setA({ schemaEnabled: v }); },
114 __nextHasNoMarginBottom: true,
115 })
116 ),
117 el(PanelBody, { title: __('Icon Style'), initialOpen: false },
118 el(SelectControl, {
119 label: __('Icon Style'), value: a.iconStyle,
120 options: [
121 { label: 'Filled box', value: 'filled' },
122 { label: 'Outline box', value: 'outline' },
123 { label: 'No box', value: 'none' },
124 ],
125 onChange: function (v) { setA({ iconStyle: v }); },
126 }),
127 el(RangeControl, {
128 label: __('Icon Size'), value: a.iconSize, min: 12, max: 36,
129 onChange: function (v) { setA({ iconSize: v }); },
130 }),
131 el(RangeControl, {
132 label: __('Box Size'), value: a.iconBoxSize, min: 24, max: 80,
133 onChange: function (v) { setA({ iconBoxSize: v }); },
134 }),
135 el(RangeControl, {
136 label: __('Box Radius'), value: a.iconRadius, min: 0, max: 40,
137 onChange: function (v) { setA({ iconRadius: v }); },
138 }),
139 el(PanelColorSettings, {
140 title: __('Icon Colors'), initialOpen: false,
141 colorSettings: [
142 { label: __('Icon Color'), value: a.iconColor, onChange: function (v) { setA({ iconColor: v || '#2563eb' }); } },
143 { label: __('Box BG'), value: a.iconBg, onChange: function (v) { setA({ iconBg: v || '#eff6ff' }); } },
144 ],
145 })
146 ),
147 el(PanelBody, { title: __('Typography'), initialOpen: false },
148 (function () {
149 var TC = getTypographyControl();
150 if (!TC) return el('p', { style: { color: '#999', fontSize: '12px', padding: '8px 0' } }, 'Typography control loading…');
151 return el(window.wp.element.Fragment, {},
152 el(TC, {
153 label: 'Label',
154 value: a.typoLabel || {},
155 onChange: function (v) { setA({ typoLabel: v }); }
156 }),
157 el(TC, {
158 label: 'Value',
159 value: a.typoValue || {},
160 onChange: function (v) { setA({ typoValue: v }); }
161 })
162 );
163 })(),
164 el(PanelColorSettings, {
165 title: __('Text Colors'), initialOpen: false,
166 colorSettings: [
167 { label: __('Label Color'), value: a.labelColor, onChange: function (v) { setA({ labelColor: v || '#6b7280' }); } },
168 { label: __('Value Color'), value: a.valueColor, onChange: function (v) { setA({ valueColor: v || '#111827' }); } },
169 { label: __('Link Color'), value: a.linkColor, onChange: function (v) { setA({ linkColor: v || '#2563eb' }); } },
170 ],
171 })
172 )
173 );
174
175 /* ── Item editor panels ── */
176 var itemPanels = el(PanelBody, { title: __('Contact Items'), initialOpen: true },
177 a.items.map(function (item, idx) {
178 return el('div', {
179 key: item.id,
180 style: { border: '1px solid #e5e7eb', borderRadius: 6, padding: 12, marginBottom: 12 }
181 },
182 el(SelectControl, {
183 label: __('Type'),
184 value: item.type,
185 options: Object.keys(TYPE_ICONS).map(function (t) { return { label: t.charAt(0).toUpperCase() + t.slice(1), value: t }; }),
186 onChange: function (v) { updateItem(a.items, item.id, 'type', v, setA); },
187 }),
188 el(TextControl, {
189 label: __('Label'),
190 value: item.label,
191 onChange: function (v) { updateItem(a.items, item.id, 'label', v, setA); },
192 }),
193 el(TextControl, {
194 label: __('Value'),
195 value: item.value,
196 onChange: function (v) { updateItem(a.items, item.id, 'value', v, setA); },
197 }),
198 el(ToggleControl, {
199 label: __('Make value a link'),
200 checked: item.linkEnabled,
201 onChange: function (v) { updateItem(a.items, item.id, 'linkEnabled', v, setA); },
202 __nextHasNoMarginBottom: true,
203 }),
204 el(Button, {
205 variant: 'link',
206 isDestructive: true,
207 onClick: function () {
208 setA({ items: a.items.filter(function (it) { return it.id !== item.id; }) });
209 }
210 }, __('Remove'))
211 );
212 }),
213 el(Button, {
214 variant: 'secondary',
215 onClick: function () {
216 setA({ items: a.items.concat([{ id: generateId(), type: 'custom', label: 'Label', value: 'Value', linkEnabled: false }]) });
217 }
218 }, __('+ Add Item'))
219 );
220
221 /* ── Preview ── */
222 var wrapStyle = Object.assign({
223 display: a.layout === 'inline' ? 'flex' : a.layout === 'grid' ? 'grid' : 'flex',
224 flexDirection: a.layout === 'stacked' ? 'column' : undefined,
225 flexWrap: a.layout === 'inline' ? 'wrap' : undefined,
226 gridTemplateColumns: a.layout === 'grid' ? 'repeat(' + a.columns + ', 1fr)' : undefined,
227 gap: a.itemSpacing + 'px',
228 }, _tv(a.typoLabel, '--bkcti-label-'), _tv(a.typoValue, '--bkcti-value-'));
229
230 var preview = el('div', { style: wrapStyle },
231 a.items.map(function (item) {
232 var linkHref = item.type === 'phone' ? 'tel:' + item.value
233 : item.type === 'email' ? 'mailto:' + item.value
234 : item.value;
235 return el('div', { key: item.id, className: 'bkbg-cti-item', style: { display: 'flex', alignItems: 'center', gap: 12 } },
236 renderIcon(item.type, a.iconStyle, a.iconBg, a.iconColor, a.iconSize, a.iconBoxSize, a.iconRadius),
237 el('div', { style: { display: 'flex', flexDirection: 'column' } },
238 a.showLabel && el('span', { className: 'bkbg-cti-label', style: { color: a.labelColor, textTransform: 'uppercase', letterSpacing: '0.05em' } }, item.label),
239 item.linkEnabled
240 ? el('a', { href: linkHref, className: 'bkbg-cti-link', style: { color: a.linkColor, textDecoration: 'none' } }, item.value)
241 : el('span', { className: 'bkbg-cti-value', style: { color: a.valueColor } }, item.value)
242 )
243 );
244 })
245 );
246
247 return el('div', null,
248 el(InspectorControls, null, itemPanels, inspector.props.children),
249 preview
250 );
251 },
252
253 save: function (props) {
254 var a = props.attributes;
255
256 function getLinkHref(item) {
257 if (item.type === 'phone') return 'tel:' + item.value.replace(/\s/g, '');
258 if (item.type === 'email') return 'mailto:' + item.value;
259 if (item.type === 'website') return item.value;
260 return item.value;
261 }
262
263 var svgMap = {
264 address: TYPE_ICONS ? undefined : '',
265 };
266
267 return el('div', {
268 className: 'bkbg-cti-wrap bkbg-cti-layout--' + a.layout,
269 style: Object.assign({
270 '--bkbg-cti-cols': a.columns,
271 '--bkbg-cti-gap': a.itemSpacing + 'px',
272 '--bkbg-cti-icon-c': a.iconColor,
273 '--bkbg-cti-icon-bg': a.iconBg,
274 '--bkbg-cti-label-c': a.labelColor,
275 '--bkbg-cti-value-c': a.valueColor,
276 '--bkbg-cti-link-c': a.linkColor,
277 '--bkbg-cti-ls': a.labelSize + 'px',
278 '--bkbg-cti-lw': a.labelWeight,
279 '--bkbg-cti-vs': a.valueSize + 'px',
280 '--bkbg-cti-vw': a.valueWeight,
281 '--bkbg-cti-icon-sz': a.iconSize + 'px',
282 '--bkbg-cti-box-sz': a.iconBoxSize + 'px',
283 '--bkbg-cti-box-r': a.iconRadius + 'px',
284 }, _tv(a.typoLabel, '--bkcti-label-'), _tv(a.typoValue, '--bkcti-value-')),
285 'data-schema': a.schemaEnabled ? '1' : '0',
286 'data-items': JSON.stringify(a.items),
287 'data-icon-style': a.iconStyle,
288 'data-show-label': a.showLabel ? '1' : '0',
289 });
290 },
291 });
292 })();
293