| 1 |
( function () { |
| 2 |
var el = wp.element.createElement; |
| 3 |
var __ = wp.i18n.__; |
| 4 |
var registerBlockType = wp.blocks.registerBlockType; |
| 5 |
var useBlockProps = wp.blockEditor.useBlockProps; |
| 6 |
var InspectorControls = wp.blockEditor.InspectorControls; |
| 7 |
var PanelColorSettings = wp.blockEditor.PanelColorSettings; |
| 8 |
var PanelBody = wp.components.PanelBody; |
| 9 |
var TextControl = wp.components.TextControl; |
| 10 |
var ToggleControl = wp.components.ToggleControl; |
| 11 |
var RangeControl = wp.components.RangeControl; |
| 12 |
var SelectControl = wp.components.SelectControl; |
| 13 |
|
| 14 |
var _ghcTC, _ghcTV; |
| 15 |
function _tc() { return _ghcTC || (_ghcTC = window.bkbgTypographyControl); } |
| 16 |
function _tv() { return _ghcTV || (_ghcTV = window.bkbgTypoCssVars); } |
| 17 |
|
| 18 |
/* ── GitHub Card preview (static mock) ── */ |
| 19 |
function EditorPreview(props) { |
| 20 |
var attr = props.attr; |
| 21 |
var isRepo = attr.mode === 'repo'; |
| 22 |
var handle = attr.username || 'username'; |
| 23 |
var repoLabel = attr.repoName || 'repository-name'; |
| 24 |
var fullName = isRepo ? handle + '/' + repoLabel : handle; |
| 25 |
|
| 26 |
var cardStyle = { |
| 27 |
background: attr.cardBg, |
| 28 |
border: '1px solid ' + attr.borderColor, |
| 29 |
borderRadius: attr.cardRadius + 'px', |
| 30 |
padding: attr.padding + 'px', |
| 31 |
maxWidth: attr.maxWidth + 'px', |
| 32 |
margin: attr.align2 === 'center' ? '0 auto' : |
| 33 |
attr.align2 === 'right' ? '0 0 0 auto' : '0', |
| 34 |
color: attr.headingColor |
| 35 |
}; |
| 36 |
|
| 37 |
var mockStats = isRepo |
| 38 |
? [{ icon: '⭐', label: '128', key: 'stars' }, { icon: '🍴', label: '34', key: 'forks' }, { icon: '👁', label: '12', key: 'watchers' }] |
| 39 |
: [{ icon: '📦', label: '32', key: 'repos' }, { icon: '👥', label: '1.2k', key: 'followers' }, { icon: '👤', label: '12', key: 'following' }]; |
| 40 |
|
| 41 |
return el('div', { className: 'bkbg-ghc-app', style: cardStyle }, |
| 42 |
/* Header row */ |
| 43 |
el('div', { style: { display: 'flex', alignItems: 'center', gap: '14px', marginBottom: '14px' } }, |
| 44 |
attr.showAvatar && el('div', { |
| 45 |
style: { |
| 46 |
width: attr.avatarSize + 'px', height: attr.avatarSize + 'px', |
| 47 |
borderRadius: isRepo ? '8px' : '50%', |
| 48 |
background: 'linear-gradient(135deg, #6366f1, #3b82f6)', |
| 49 |
flexShrink: 0, display: 'flex', alignItems: 'center', justifyContent: 'center', |
| 50 |
fontSize: '24px', color: '#fff' |
| 51 |
} |
| 52 |
}, isRepo ? '📁' : '👤'), |
| 53 |
el('div', {}, |
| 54 |
el('div', { className: 'bkbg-ghc-name-row', style: { color: attr.linkColor } }, fullName), |
| 55 |
attr.showBio && el('div', { className: 'bkbg-ghc-handle', style: { color: attr.metaColor, marginTop: '4px' } }, |
| 56 |
isRepo ? 'A great open source repository' : 'Software Developer & Creator' |
| 57 |
) |
| 58 |
) |
| 59 |
), |
| 60 |
/* Description */ |
| 61 |
attr.showBio && el('div', { className: 'bkbg-ghc-desc', style: { color: attr.descColor, marginBottom: '16px' } }, |
| 62 |
isRepo |
| 63 |
? 'This repository contains amazing code that solves real-world problems efficiently and elegantly.' |
| 64 |
: 'Passionate about building great software. Open source contributor.' |
| 65 |
), |
| 66 |
/* Language + topics */ |
| 67 |
isRepo && el('div', { className: 'bkbg-ghc-meta-row', style: { marginBottom: '14px' } }, |
| 68 |
attr.showLanguage && el('span', { |
| 69 |
className: 'bkbg-ghc-lang', style: { color: attr.metaColor } |
| 70 |
}, el('span', { style: { width: '10px', height: '10px', borderRadius: '50%', background: '#3b82f6', display: 'inline-block' } }), 'TypeScript'), |
| 71 |
attr.showTopics && ['wordpress', 'gutenberg', 'blocks'].map(function (t, i) { |
| 72 |
return el('span', { key: i, className: 'bkbg-ghc-topic', style: { background: 'rgba(56,139,253,0.15)', color: attr.linkColor } }, t); |
| 73 |
}) |
| 74 |
), |
| 75 |
/* Stats */ |
| 76 |
attr.showStats && el('div', { className: 'bkbg-ghc-stats' }, |
| 77 |
mockStats.map(function (s) { |
| 78 |
return el('div', { key: s.key, className: 'bkbg-ghc-stat', style: { background: attr.statBg, border: '1px solid ' + attr.borderColor } }, |
| 79 |
el('div', { className: 'bkbg-ghc-stat-val', style: { color: attr.headingColor } }, s.label), |
| 80 |
el('div', { className: 'bkbg-ghc-stat-lbl', style: { color: attr.metaColor } }, s.key) |
| 81 |
); |
| 82 |
}) |
| 83 |
), |
| 84 |
/* Footer */ |
| 85 |
attr.showLastUpdate && el('div', { className: 'bkbg-ghc-footer', style: { color: attr.metaColor } }, |
| 86 |
'Updated 2 hours ago' |
| 87 |
) |
| 88 |
); |
| 89 |
} |
| 90 |
|
| 91 |
registerBlockType('blockenberg/github-card', { |
| 92 |
edit: function (props) { |
| 93 |
var attr = props.attributes; |
| 94 |
var setAttr = props.setAttributes; |
| 95 |
var blockProps = useBlockProps({ style: Object.assign({ background: attr.sectionBg || undefined, padding: '20px' }, _tv()(attr.typoHeading, '--bkbg-ghc-hd-'), _tv()(attr.typoBody, '--bkbg-ghc-bd-'), _tv()(attr.typoMeta, '--bkbg-ghc-mt-')) }); |
| 96 |
|
| 97 |
var inspector = el(InspectorControls, {}, |
| 98 |
/* Source */ |
| 99 |
el(PanelBody, { title: __('GitHub Source', 'blockenberg'), initialOpen: true }, |
| 100 |
el(SelectControl, { |
| 101 |
label: __('Card Type', 'blockenberg'), |
| 102 |
value: attr.mode, |
| 103 |
options: [{ label: 'Repository', value: 'repo' }, { label: 'User Profile', value: 'user' }], |
| 104 |
onChange: function (v) { setAttr({ mode: v }); }, |
| 105 |
__nextHasNoMarginBottom: true |
| 106 |
}), |
| 107 |
el('div', { style: { marginTop: '12px' } }), |
| 108 |
el(TextControl, { |
| 109 |
label: __('GitHub Username', 'blockenberg'), |
| 110 |
value: attr.username, |
| 111 |
onChange: function (v) { setAttr({ username: v }); }, |
| 112 |
placeholder: 'e.g. torvalds', |
| 113 |
__nextHasNoMarginBottom: true |
| 114 |
}), |
| 115 |
attr.mode === 'repo' && el('div', {}, |
| 116 |
el('div', { style: { marginTop: '8px' } }), |
| 117 |
el(TextControl, { |
| 118 |
label: __('Repository Name', 'blockenberg'), |
| 119 |
value: attr.repoName, |
| 120 |
onChange: function (v) { setAttr({ repoName: v }); }, |
| 121 |
placeholder: 'e.g. linux', |
| 122 |
help: __('Just the repo name, not the full URL.', 'blockenberg'), |
| 123 |
__nextHasNoMarginBottom: true |
| 124 |
}) |
| 125 |
), |
| 126 |
el('div', { style: { marginTop: '8px' } }), |
| 127 |
el(RangeControl, { label: __('Cache Duration (minutes)', 'blockenberg'), value: attr.cacheMinutes, min: 5, max: 1440, onChange: function (v) { setAttr({ cacheMinutes: v }); }, help: __('Stores API response in localStorage to avoid rate limits.', 'blockenberg'), __nextHasNoMarginBottom: true }), |
| 128 |
el('div', { style: { marginTop: '8px' } }), |
| 129 |
el(ToggleControl, { label: __('Open Links in New Tab', 'blockenberg'), checked: attr.openInNewTab, onChange: function (v) { setAttr({ openInNewTab: v }); }, __nextHasNoMarginBottom: true }) |
| 130 |
), |
| 131 |
/* Display Fields */ |
| 132 |
el(PanelBody, { title: __('Display', 'blockenberg'), initialOpen: false }, |
| 133 |
el(ToggleControl, { label: __('Show Avatar', 'blockenberg'), checked: attr.showAvatar, onChange: function (v) { setAttr({ showAvatar: v }); }, __nextHasNoMarginBottom: true }), |
| 134 |
el(ToggleControl, { label: __('Show Bio / Description', 'blockenberg'), checked: attr.showBio, onChange: function (v) { setAttr({ showBio: v }); }, __nextHasNoMarginBottom: true }), |
| 135 |
el(ToggleControl, { label: __('Show Stats', 'blockenberg'), checked: attr.showStats, onChange: function (v) { setAttr({ showStats: v }); }, __nextHasNoMarginBottom: true }), |
| 136 |
attr.mode === 'repo' && el(ToggleControl, { label: __('Show Language', 'blockenberg'), checked: attr.showLanguage, onChange: function (v) { setAttr({ showLanguage: v }); }, __nextHasNoMarginBottom: true }), |
| 137 |
attr.mode === 'repo' && el(ToggleControl, { label: __('Show Topics', 'blockenberg'), checked: attr.showTopics, onChange: function (v) { setAttr({ showTopics: v }); }, __nextHasNoMarginBottom: true }), |
| 138 |
el(ToggleControl, { label: __('Show Last Updated', 'blockenberg'), checked: attr.showLastUpdate, onChange: function (v) { setAttr({ showLastUpdate: v }); }, __nextHasNoMarginBottom: true }) |
| 139 |
), |
| 140 |
/* Layout */ |
| 141 |
el(PanelBody, { title: __('Layout', 'blockenberg'), initialOpen: false }, |
| 142 |
el(SelectControl, { |
| 143 |
label: __('Alignment', 'blockenberg'), |
| 144 |
value: attr.align2, |
| 145 |
options: [{ label: 'Left', value: 'left' }, { label: 'Center', value: 'center' }, { label: 'Right', value: 'right' }], |
| 146 |
onChange: function (v) { setAttr({ align2: v }); }, |
| 147 |
__nextHasNoMarginBottom: true |
| 148 |
}), |
| 149 |
el('div', { style: { marginTop: '8px' } }), |
| 150 |
el(RangeControl, { label: __('Max Width (px)', 'blockenberg'), value: attr.maxWidth, min: 280, max: 800, onChange: function (v) { setAttr({ maxWidth: v }); }, __nextHasNoMarginBottom: true }), |
| 151 |
el('div', { style: { marginTop: '8px' } }), |
| 152 |
el(RangeControl, { label: __('Padding (px)', 'blockenberg'), value: attr.padding, min: 12, max: 48, onChange: function (v) { setAttr({ padding: v }); }, __nextHasNoMarginBottom: true }), |
| 153 |
el('div', { style: { marginTop: '8px' } }), |
| 154 |
el(RangeControl, { label: __('Corner Radius (px)', 'blockenberg'), value: attr.cardRadius, min: 0, max: 32, onChange: function (v) { setAttr({ cardRadius: v }); }, __nextHasNoMarginBottom: true }), |
| 155 |
el('div', { style: { marginTop: '8px' } }), |
| 156 |
el(RangeControl, { label: __('Avatar Size (px)', 'blockenberg'), value: attr.avatarSize, min: 32, max: 120, onChange: function (v) { setAttr({ avatarSize: v }); }, __nextHasNoMarginBottom: true }) |
| 157 |
), |
| 158 |
/* Typography */ |
| 159 |
el(PanelBody, { title: __('Typography', 'blockenberg'), initialOpen: false }, |
| 160 |
_tc()({ label: __('Heading', 'blockenberg'), value: attr.typoHeading, onChange: function (v) { setAttr({ typoHeading: v }); } }), |
| 161 |
_tc()({ label: __('Body', 'blockenberg'), value: attr.typoBody, onChange: function (v) { setAttr({ typoBody: v }); } }), |
| 162 |
_tc()({ label: __('Meta', 'blockenberg'), value: attr.typoMeta, onChange: function (v) { setAttr({ typoMeta: v }); } }) |
| 163 |
), |
| 164 |
/* Colors */ |
| 165 |
el(PanelColorSettings, { |
| 166 |
title: __('Colors', 'blockenberg'), |
| 167 |
initialOpen: false, |
| 168 |
colorSettings: [ |
| 169 |
{ label: __('Card Background', 'blockenberg'), value: attr.cardBg, onChange: function (v) { setAttr({ cardBg: v || '#0d1117' }); } }, |
| 170 |
{ label: __('Heading / Name', 'blockenberg'), value: attr.headingColor, onChange: function (v) { setAttr({ headingColor: v || '#e6edf3' }); } }, |
| 171 |
{ label: __('Description', 'blockenberg'), value: attr.descColor, onChange: function (v) { setAttr({ descColor: v || '#8b949e' }); } }, |
| 172 |
{ label: __('Meta / Stats Label', 'blockenberg'), value: attr.metaColor, onChange: function (v) { setAttr({ metaColor: v || '#8b949e' }); } }, |
| 173 |
{ label: __('Link / Accent', 'blockenberg'), value: attr.linkColor, onChange: function (v) { setAttr({ linkColor: v || '#58a6ff' }); } }, |
| 174 |
{ label: __('Stat Tile Background', 'blockenberg'), value: attr.statBg, onChange: function (v) { setAttr({ statBg: v || '#161b22' }); } }, |
| 175 |
{ label: __('Border', 'blockenberg'), value: attr.borderColor, onChange: function (v) { setAttr({ borderColor: v || '#30363d' }); } }, |
| 176 |
{ label: __('Section Background', 'blockenberg'), value: attr.sectionBg, onChange: function (v) { setAttr({ sectionBg: v || '' }); } } |
| 177 |
] |
| 178 |
}) |
| 179 |
); |
| 180 |
|
| 181 |
return el('div', blockProps, |
| 182 |
inspector, |
| 183 |
(!attr.username) |
| 184 |
? el('div', { |
| 185 |
style: { |
| 186 |
textAlign: 'center', padding: '40px', border: '2px dashed #30363d', |
| 187 |
borderRadius: attr.cardRadius + 'px', color: '#8b949e', fontFamily: 'system-ui, sans-serif' |
| 188 |
} |
| 189 |
}, |
| 190 |
el('div', { style: { fontSize: '32px', marginBottom: '12px' } }, '𝖦'), |
| 191 |
el('div', { style: { fontWeight: 600, marginBottom: '8px' } }, 'GitHub Card'), |
| 192 |
el('div', { style: { fontSize: '14px' } }, 'Enter a GitHub username in the block settings to preview.') |
| 193 |
) |
| 194 |
: el(EditorPreview, { attr: attr }) |
| 195 |
); |
| 196 |
}, |
| 197 |
|
| 198 |
save: function (props) { |
| 199 |
var attr = props.attributes; |
| 200 |
var blockProps = useBlockProps.save(); |
| 201 |
return el('div', blockProps, |
| 202 |
el('div', { |
| 203 |
className: 'bkbg-ghc-app', |
| 204 |
'data-opts': JSON.stringify(attr) |
| 205 |
}) |
| 206 |
); |
| 207 |
} |
| 208 |
}); |
| 209 |
}() ); |
| 210 |
|