PluginProbe
Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor / 2.0.14
Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor v2.0.14
2.0.14 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 / email-signature / index.js

index.js in Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor 2.0.14, at blocks/email-signature/index.js

268 lines 18.0 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, useBlockProps, MediaUpload, PanelColorSettings } = window.wp.blockEditor;
5 const { PanelBody, RangeControl, SelectControl, ToggleControl, TextControl, Button } = window.wp.components;
6 const { __ } = window.wp.i18n;
7
8 var _esigTC, _esigTV;
9 function _tc() { return _esigTC || (_esigTC = window.bkbgTypographyControl); }
10 function _tv(t, p) { return (_esigTV || (_esigTV = window.bkbgTypoCssVars)) ? _esigTV(t, p) : {}; }
11
12 const STYLES = [
13 { label: 'Modern (horizontal)', value: 'modern' },
14 { label: 'Minimal (text only)', value: 'minimal' },
15 { label: 'Branded (accent bar)', value: 'branded' },
16 { label: 'Compact (tight)', value: 'compact' },
17 ];
18 const DIVIDER_STYLES = [
19 { label: 'Line', value: 'line' },
20 { label: 'Accent Bar', value: 'accent' },
21 { label: 'None', value: 'none' },
22 ];
23 const SOCIAL_DEFS = [
24 { key: 'twitterUrl', label: 'X / Twitter', icon: '𝕏', color: '#000000' },
25 { key: 'linkedinUrl', label: 'LinkedIn', icon: 'in', color: '#0077b5' },
26 { key: 'githubUrl', label: 'GitHub', icon: '⌂', color: '#24292e' },
27 { key: 'instagramUrl', label: 'Instagram', icon: '◈', color: '#e1306c' },
28 { key: 'youtubeUrl', label: 'YouTube', icon: '▶', color: '#ff0000' },
29 ];
30
31 function wrapStyle(a) {
32 return Object.assign({
33 '--bkbg-esig-accent': a.accentColor,
34 '--bkbg-esig-name-c': a.nameColor,
35 '--bkbg-esig-title-c': a.titleColor,
36 '--bkbg-esig-company-c': a.companyColor,
37 '--bkbg-esig-info-c': a.infoColor,
38 '--bkbg-esig-divider-c': a.dividerColor,
39 '--bkbg-esig-social-c': a.socialColor,
40 '--bkbg-esig-bg': a.bgColor,
41 '--bkbg-esig-name-sz': a.nameSize + 'px',
42 '--bkbg-esig-name-w': a.nameWeight,
43 '--bkbg-esig-name-lh': a.nameLineHeight,
44 '--bkbg-esig-title-sz': a.titleSize + 'px',
45 '--bkbg-esig-title-w': a.titleWeight,
46 '--bkbg-esig-title-lh': a.titleLineHeight,
47 '--bkbg-esig-info-sz': a.infoSize + 'px',
48 '--bkbg-esig-avatar-sz': a.avatarSize + 'px',
49 '--bkbg-esig-avatar-r': a.avatarRadius + '%',
50 '--bkbg-esig-social-icon-sz':a.socialIconSize + 'px',
51 }, _tv(a.typoName || {}, '--bkbg-esig-nm-'), _tv(a.typoJobTitle || {}, '--bkbg-esig-jt-'));
52 }
53
54 function SigPreview({ a }) {
55 const hasSocials = a.showSocials && SOCIAL_DEFS.some(s => a[s.key]);
56
57 return el('div', { className: 'bkbg-esig-sig bkbg-esig-style--' + a.style },
58 /* Avatar */
59 a.showAvatar && el('div', { className: 'bkbg-esig-avatar-col' },
60 a.avatarUrl
61 ? el('img', { src: a.avatarUrl, alt: a.name, className: 'bkbg-esig-avatar' })
62 : el('div', { className: 'bkbg-esig-avatar-placeholder' },
63 el('span', { className: 'dashicons dashicons-admin-users', style: { fontSize: Math.round(a.avatarSize * 0.44) + 'px', color: a.accentColor } })
64 ),
65 ),
66
67 /* Content */
68 el('div', { className: 'bkbg-esig-body' },
69 /* Name + title row */
70 el('div', { className: 'bkbg-esig-identity' },
71 el('span', { className: 'bkbg-esig-name' }, a.name),
72 el('span', { className: 'bkbg-esig-title' }, a.title),
73 a.company && el('span', { className: 'bkbg-esig-company' }, a.company),
74 ),
75
76 /* Divider */
77 a.dividerStyle !== 'none' && el('div', { className: 'bkbg-esig-divider bkbg-esig-divider--' + a.dividerStyle }),
78
79 /* Contact info */
80 el('div', { className: 'bkbg-esig-contact' },
81 a.showPhone && a.phone && el('span', { className: 'bkbg-esig-info-row' },
82 el('span', { className: 'bkbg-esig-info-icon' }, '📞'),
83 el('a', { href: 'tel:' + a.phone, className: 'bkbg-esig-info-link' }, a.phone),
84 ),
85 a.showEmail && a.email && el('span', { className: 'bkbg-esig-info-row' },
86 el('span', { className: 'bkbg-esig-info-icon' }, '✉'),
87 el('a', { href: 'mailto:' + a.email, className: 'bkbg-esig-info-link' }, a.email),
88 ),
89 a.showWebsite && a.website && el('span', { className: 'bkbg-esig-info-row' },
90 el('span', { className: 'bkbg-esig-info-icon' }, '🌐'),
91 el('a', { href: 'https://' + a.website.replace(/^https?:\/\//, ''), className: 'bkbg-esig-info-link', target: '_blank', rel: 'noopener' }, a.website.replace(/^https?:\/\//, '')),
92 ),
93 ),
94
95 /* Social icons */
96 hasSocials && el('div', { className: 'bkbg-esig-socials' },
97 SOCIAL_DEFS.filter(s => a[s.key]).map((s, i) =>
98 el('a', { key: i, className: 'bkbg-esig-social-icon', href: s.key === 'linkedinUrl' || s.key === 'twitterUrl' || s.key === 'githubUrl' ? a[s.key] : a[s.key], target: '_blank', rel: 'noopener noreferrer', title: s.label, style: { color: a.socialColor } },
99 el('span', { style: { fontFamily: 'sans-serif', fontStyle: 'normal', fontWeight: 700 } }, s.icon),
100 )
101 )
102 ),
103
104 /* Banner */
105 a.showBanner && a.bannerUrl && el('div', { className: 'bkbg-esig-banner' },
106 el('a', { href: a.bannerLink, target: '_blank', rel: 'noopener' },
107 el('img', { src: a.bannerUrl, alt: '', className: 'bkbg-esig-banner-img', style: { maxWidth: a.bannerWidth + 'px' } }),
108 )
109 ),
110 ),
111 );
112 }
113
114 registerBlockType('blockenberg/email-signature', {
115 edit: function (props) {
116 const { attributes: a, setAttributes } = props;
117 const blockProps = useBlockProps({ className: 'bkbg-esig-wrap', style: wrapStyle(a) });
118
119 return el('div', blockProps,
120 el(InspectorControls, null,
121
122 el(PanelBody, { title: __('Identity'), initialOpen: true },
123 el(TextControl, { label: __('Full Name'), value: a.name, onChange: v => setAttributes({ name: v }) }),
124 el(TextControl, { label: __('Job Title'), value: a.title, onChange: v => setAttributes({ title: v }) }),
125 el(TextControl, { label: __('Company'), value: a.company, onChange: v => setAttributes({ company: v }) }),
126 ),
127
128 el(PanelBody, { title: __('Contact Info'), initialOpen: false },
129 el(ToggleControl, { label: __('Show Phone'), checked: a.showPhone, onChange: v => setAttributes({ showPhone: v }), __nextHasNoMarginBottom: true }),
130 a.showPhone && el(TextControl, { label: __('Phone'), value: a.phone, onChange: v => setAttributes({ phone: v }) }),
131 el(ToggleControl, { label: __('Show Email'), checked: a.showEmail, onChange: v => setAttributes({ showEmail: v }), __nextHasNoMarginBottom: true }),
132 a.showEmail && el(TextControl, { label: __('Email Address'), value: a.email, onChange: v => setAttributes({ email: v }) }),
133 el(ToggleControl, { label: __('Show Website'), checked: a.showWebsite, onChange: v => setAttributes({ showWebsite: v }), __nextHasNoMarginBottom: true }),
134 a.showWebsite && el(TextControl, { label: __('Website'), value: a.website, onChange: v => setAttributes({ website: v }) }),
135 ),
136
137 el(PanelBody, { title: __('Avatar'), initialOpen: false },
138 el(ToggleControl, { label: __('Show Avatar'), checked: a.showAvatar, onChange: v => setAttributes({ showAvatar: v }), __nextHasNoMarginBottom: true }),
139 a.showAvatar && ( a.avatarUrl
140 ? el('div', null,
141 el('img', { src: a.avatarUrl, style: { width: a.avatarSize + 'px', height: a.avatarSize + 'px', objectFit: 'cover', borderRadius: a.avatarRadius + '%', display: 'block', marginBottom: 8 } }),
142 el(Button, { isDestructive: true, isSmall: true, onClick: () => setAttributes({ avatarUrl: '', avatarId: 0 }) }, __('Remove')),
143 )
144 : el(MediaUpload, {
145 onSelect: m => setAttributes({ avatarUrl: m.url, avatarId: m.id }),
146 allowedTypes: ['image'],
147 value: a.avatarId,
148 render: ({ open }) => el(Button, { variant: 'secondary', onClick: open, style: { width: '100%', justifyContent: 'center' } }, __('Upload Avatar')),
149 })
150 ),
151 el(RangeControl, { label: __('Avatar Size (px)'), value: a.avatarSize, min: 40, max: 200, onChange: v => setAttributes({ avatarSize: v }) }),
152 el(RangeControl, { label: __('Avatar Radius (%)'), value: a.avatarRadius, min: 0, max: 50, onChange: v => setAttributes({ avatarRadius: v }) }),
153 ),
154
155 el(PanelBody, { title: __('Social Links'), initialOpen: false },
156 el(ToggleControl, { label: __('Show Social Icons'), checked: a.showSocials, onChange: v => setAttributes({ showSocials: v }), __nextHasNoMarginBottom: true }),
157 SOCIAL_DEFS.map(s => el(TextControl, {
158 key: s.key,
159 label: s.label + ' URL',
160 value: a[s.key],
161 onChange: v => setAttributes({ [s.key]: v }),
162 })),
163 ),
164
165 el(PanelBody, { title: __('Banner Image'), initialOpen: false },
166 el(ToggleControl, { label: __('Show Banner'), checked: a.showBanner, onChange: v => setAttributes({ showBanner: v }), __nextHasNoMarginBottom: true }),
167 a.showBanner && ( a.bannerUrl
168 ? el('div', null,
169 el('img', { src: a.bannerUrl, style: { maxWidth: '100%', display: 'block', marginBottom: 8 } }),
170 el(Button, { isDestructive: true, isSmall: true, onClick: () => setAttributes({ bannerUrl: '', bannerId: 0 }) }, __('Remove Banner')),
171 )
172 : el(MediaUpload, {
173 onSelect: m => setAttributes({ bannerUrl: m.url, bannerId: m.id }),
174 allowedTypes: ['image'],
175 value: a.bannerId,
176 render: ({ open }) => el(Button, { variant: 'secondary', onClick: open, style: { width: '100%', justifyContent: 'center' } }, __('Upload Banner')),
177 })
178 ),
179 a.showBanner && el(TextControl, { label: __('Banner Link URL'), value: a.bannerLink, onChange: v => setAttributes({ bannerLink: v }) }),
180 a.showBanner && el(RangeControl, { label: __('Banner Max Width (px)'), value: a.bannerWidth, min: 160, max: 600, onChange: v => setAttributes({ bannerWidth: v }) }),
181 ),
182
183 el(PanelBody, { title: __('Style'), initialOpen: false },
184 el(SelectControl, { label: __('Signature Style'), value: a.style, options: STYLES, onChange: v => setAttributes({ style: v }) }),
185 el(SelectControl, { label: __('Divider Style'), value: a.dividerStyle, options: DIVIDER_STYLES, onChange: v => setAttributes({ dividerStyle: v }) }),
186 ),
187
188 el(PanelBody, { title: __('Typography'), initialOpen: false },
189 _tc() && el(_tc(), { label: __('Name'), typo: a.typoName || {}, onChange: v => setAttributes({ typoName: v }), defaultSize: a.nameSize || 17 }),
190 _tc() && el(_tc(), { label: __('Job Title'), typo: a.typoJobTitle || {}, onChange: v => setAttributes({ typoJobTitle: v }), defaultSize: a.titleSize || 13 }),
191 el(RangeControl, { label: __('Info Size (px)'), value: a.infoSize, min: 10, max: 18, onChange: v => setAttributes({ infoSize: v }) }),
192 el(RangeControl, { label: __('Social Icon Size (px)'), value: a.socialIconSize, min: 12, max: 28, onChange: v => setAttributes({ socialIconSize: v }) }),
193 ),
194
195 el(PanelColorSettings, {
196 title: __('Colors'), initialOpen: false,
197 colorSettings: [
198 { label: __('Background'), value: a.bgColor, onChange: v => setAttributes({ bgColor: v || '#ffffff' }) },
199 { label: __('Name'), value: a.nameColor, onChange: v => setAttributes({ nameColor: v || '#0f172a' }) },
200 { label: __('Job Title'), value: a.titleColor, onChange: v => setAttributes({ titleColor: v || '#6c3fb5' }) },
201 { label: __('Company'), value: a.companyColor, onChange: v => setAttributes({ companyColor: v || '#374151' }) },
202 { label: __('Info Text'), value: a.infoColor, onChange: v => setAttributes({ infoColor: v || '#64748b' }) },
203 { label: __('Accent'), value: a.accentColor, onChange: v => setAttributes({ accentColor: v || '#6c3fb5' }) },
204 { label: __('Divider'), value: a.dividerColor, onChange: v => setAttributes({ dividerColor: v || '#e2e8f0' }) },
205 { label: __('Social Icons'), value: a.socialColor, onChange: v => setAttributes({ socialColor: v || '#64748b' }) },
206 ]
207 }),
208 ),
209
210 /* ---- Canvas preview ---- */
211 el('div', { className: 'bkbg-esig-editor-label' },
212 el('span', { className: 'dashicons dashicons-email-alt' }),
213 el('span', null, ' ' + __('Email Signature Preview')),
214 ),
215 el(SigPreview, { a }),
216 );
217 },
218
219 save: function ({ attributes: a }) {
220 const hasSocials = a.showSocials && SOCIAL_DEFS.some(s => a[s.key]);
221 return el('div', {
222 className: 'bkbg-esig-wrap bkbg-esig-style--' + a.style,
223 style: wrapStyle(a),
224 },
225 el('div', { className: 'bkbg-esig-sig' },
226 a.showAvatar && a.avatarUrl && el('div', { className: 'bkbg-esig-avatar-col' },
227 el('img', { src: a.avatarUrl, alt: a.name, className: 'bkbg-esig-avatar' }),
228 ),
229 el('div', { className: 'bkbg-esig-body' },
230 el('div', { className: 'bkbg-esig-identity' },
231 el('span', { className: 'bkbg-esig-name' }, a.name),
232 el('span', { className: 'bkbg-esig-title' }, a.title),
233 a.company && el('span', { className: 'bkbg-esig-company' }, a.company),
234 ),
235 a.dividerStyle !== 'none' && el('div', { className: 'bkbg-esig-divider bkbg-esig-divider--' + a.dividerStyle }),
236 el('div', { className: 'bkbg-esig-contact' },
237 a.showPhone && a.phone && el('span', { className: 'bkbg-esig-info-row' },
238 el('span', { className: 'bkbg-esig-info-icon' }, '📞'),
239 el('a', { href: 'tel:' + a.phone, className: 'bkbg-esig-info-link' }, a.phone),
240 ),
241 a.showEmail && a.email && el('span', { className: 'bkbg-esig-info-row' },
242 el('span', { className: 'bkbg-esig-info-icon' }, '✉'),
243 el('a', { href: 'mailto:' + a.email, className: 'bkbg-esig-info-link' }, a.email),
244 ),
245 a.showWebsite && a.website && el('span', { className: 'bkbg-esig-info-row' },
246 el('span', { className: 'bkbg-esig-info-icon' }, '🌐'),
247 el('a', { href: 'https://' + a.website.replace(/^https?:\/\//, ''), className: 'bkbg-esig-info-link', target: '_blank', rel: 'noopener noreferrer' }, a.website.replace(/^https?:\/\//, '')),
248 ),
249 ),
250 hasSocials && el('div', { className: 'bkbg-esig-socials' },
251 SOCIAL_DEFS.filter(s => a[s.key]).map((s, i) =>
252 el('a', { key: i, className: 'bkbg-esig-social-icon', href: a[s.key], target: '_blank', rel: 'noopener noreferrer', title: s.label, style: { color: a.socialColor } },
253 el('span', { style: { fontFamily: 'sans-serif', fontStyle: 'normal', fontWeight: 700, fontSize: a.socialIconSize + 'px' } }, s.icon),
254 )
255 )
256 ),
257 a.showBanner && a.bannerUrl && el('div', { className: 'bkbg-esig-banner' },
258 el('a', { href: a.bannerLink, target: '_blank', rel: 'noopener noreferrer' },
259 el('img', { src: a.bannerUrl, alt: '', className: 'bkbg-esig-banner-img', style: { maxWidth: a.bannerWidth + 'px' } }),
260 )
261 ),
262 ),
263 ),
264 );
265 }
266 });
267 }() );
268