| 1 |
(function () { |
| 2 |
'use strict'; |
| 3 |
|
| 4 |
function typoCssVarsForEl(typo, prefix, el) { |
| 5 |
if (!typo || typeof typo !== 'object') return; |
| 6 |
var m = { |
| 7 |
family: 'font-family', weight: 'font-weight', |
| 8 |
transform: 'text-transform', style: 'font-style', decoration: 'text-decoration' |
| 9 |
}; |
| 10 |
Object.keys(m).forEach(function (k) { |
| 11 |
if (typo[k]) el.style.setProperty(prefix + m[k], typo[k]); |
| 12 |
}); |
| 13 |
var r = { |
| 14 |
size: 'font-size', lineHeight: 'line-height', |
| 15 |
letterSpacing: 'letter-spacing', wordSpacing: 'word-spacing' |
| 16 |
}; |
| 17 |
Object.keys(r).forEach(function (k) { |
| 18 |
['Desktop', 'Tablet', 'Mobile'].forEach(function (d, i) { |
| 19 |
var v = typo[k + d]; |
| 20 |
if (v === undefined || v === '') return; |
| 21 |
var suffix = ['-d', '-t', '-m'][i]; |
| 22 |
var unit = typo[k + 'Unit'] || ('size' === k ? 'px' : (k === 'lineHeight' ? '' : 'px')); |
| 23 |
el.style.setProperty(prefix + r[k] + suffix, v + unit); |
| 24 |
}); |
| 25 |
}); |
| 26 |
} |
| 27 |
|
| 28 |
function mk(tag, cls, styles) { |
| 29 |
var d = document.createElement(tag); |
| 30 |
if (cls) d.className = cls; |
| 31 |
if (styles) Object.keys(styles).forEach(function (k) { d.style[k] = styles[k]; }); |
| 32 |
return d; |
| 33 |
} |
| 34 |
function tx(tag, cls, text, styles) { |
| 35 |
var d = mk(tag, cls, styles); |
| 36 |
d.textContent = text; |
| 37 |
return d; |
| 38 |
} |
| 39 |
function ap(parent) { |
| 40 |
Array.prototype.slice.call(arguments, 1).forEach(function (c) { if (c) parent.appendChild(c); }); |
| 41 |
return parent; |
| 42 |
} |
| 43 |
|
| 44 |
var categoryLabels = { |
| 45 |
'new-feature': '🆕 New Feature', |
| 46 |
'improvement': '⚡ Improvement', |
| 47 |
'bugfix': '🐛 Bug Fix', |
| 48 |
'deprecation': '⚠️ Deprecation', |
| 49 |
'security': '🔒 Security', |
| 50 |
'integration': '📦 Integration' |
| 51 |
}; |
| 52 |
var statusLabels = { |
| 53 |
'available': '� |
| 54 |
Available Now', |
| 55 |
'beta': '🧪 Beta', |
| 56 |
'coming-soon': '🚀 Coming Soon', |
| 57 |
'deprecated': '⚠️ Deprecated' |
| 58 |
}; |
| 59 |
|
| 60 |
function init() { |
| 61 |
document.querySelectorAll('.bkbg-feature-announcement-app').forEach(function (appEl) { |
| 62 |
if (appEl.dataset.rendered) return; |
| 63 |
appEl.dataset.rendered = '1'; |
| 64 |
|
| 65 |
var opts; |
| 66 |
try { opts = JSON.parse(appEl.dataset.opts || '{}'); } catch (e) { opts = {}; } |
| 67 |
|
| 68 |
var o = Object.assign({ |
| 69 |
featureName: 'Feature Name', version: 'v1.0', showVersion: true, |
| 70 |
releaseDate: '', showDate: false, |
| 71 |
category: 'new-feature', status: 'available', |
| 72 |
featureIcon: '✨', showIcon: true, |
| 73 |
tagline: '', description: '', showDescription: true, |
| 74 |
highlights: [], showHighlights: true, highlightsLabel: "What's new", |
| 75 |
availablePlans: [], showPlans: true, plansLabel: 'Available on', |
| 76 |
ctaText: '', ctaUrl: '#', showCta: true, |
| 77 |
ctaSecondaryText: '', ctaSecondaryUrl: '#', showSecondaryCta: false, |
| 78 |
accentPosition: 'top', |
| 79 |
fontSize: 15, featureNameSize: 26, taglineSize: 16, |
| 80 |
lineHeight: 170, borderRadius: 12, |
| 81 |
bgColor: '#ffffff', borderColor: '#e2e8f0', |
| 82 |
accentColor: '#7c3aed', accentStripe: '#7c3aed', |
| 83 |
featureNameColor: '#0f172a', taglineColor: '#374151', textColor: '#4b5563', |
| 84 |
versionBg: '#ede9fe', versionColor: '#5b21b6', |
| 85 |
categoryBg: '#f0fdf4', categoryColor: '#14532d', |
| 86 |
statusBg: '#dcfce7', statusColor: '#14532d', |
| 87 |
highlightIconColor: '#7c3aed', |
| 88 |
planBg: '#f5f3ff', planColor: '#5b21b6', |
| 89 |
ctaBg: '#7c3aed', ctaColor: '#ffffff', |
| 90 |
ctaSecondaryColor: '#7c3aed' |
| 91 |
}, opts); |
| 92 |
|
| 93 |
// ── Block container ─────────────────────────────────── |
| 94 |
var block = mk('div', 'bkbg-fan-block' + (o.accentPosition === 'left' ? ' has-accent-left' : ''), { |
| 95 |
background: o.bgColor, |
| 96 |
border: '1px solid ' + o.borderColor, |
| 97 |
borderRadius: o.borderRadius + 'px', |
| 98 |
overflow: 'hidden', |
| 99 |
position: 'relative' |
| 100 |
}); |
| 101 |
typoCssVarsForEl(o.typoName, '--bkbg-fan-nm-', block); |
| 102 |
typoCssVarsForEl(o.typoTagline, '--bkbg-fan-tl-', block); |
| 103 |
typoCssVarsForEl(o.typoBody, '--bkbg-fan-bd-', block); |
| 104 |
|
| 105 |
// ── Accent stripes ──────────────────────────────────── |
| 106 |
if (o.accentPosition === 'top') { |
| 107 |
ap(block, mk('div', 'bkbg-fan-accent-top', { background: o.accentStripe })); |
| 108 |
} else if (o.accentPosition === 'left') { |
| 109 |
ap(block, mk('div', 'bkbg-fan-accent-left', { background: o.accentStripe })); |
| 110 |
} |
| 111 |
|
| 112 |
// ── Inner ───────────────────────────────────────────── |
| 113 |
var inner = mk('div', 'bkbg-fan-inner'); |
| 114 |
|
| 115 |
// Meta badges row |
| 116 |
var meta = mk('div', 'bkbg-fan-meta'); |
| 117 |
if (o.showIcon && o.featureIcon) { |
| 118 |
var fanIconType = o.featureIconType || 'custom-char'; |
| 119 |
var fanIconSpan = mk('span', 'bkbg-fan-icon'); |
| 120 |
if (fanIconType !== 'custom-char' && window.bkbgIconPicker) { |
| 121 |
fanIconSpan.appendChild(window.bkbgIconPicker.buildFrontendIcon(fanIconType, o.featureIcon, o.featureIconDashicon, o.featureIconImageUrl, o.featureIconDashiconColor)); |
| 122 |
} else { |
| 123 |
fanIconSpan.textContent = o.featureIcon; |
| 124 |
} |
| 125 |
ap(meta, fanIconSpan); |
| 126 |
} |
| 127 |
// Category badge |
| 128 |
var catLabel = categoryLabels[o.category] || o.category; |
| 129 |
var catBadge = tx('span', 'bkbg-fan-badge', catLabel, { background: o.categoryBg, color: o.categoryColor }); |
| 130 |
ap(meta, catBadge); |
| 131 |
// Version badge |
| 132 |
if (o.showVersion && o.version) { |
| 133 |
ap(meta, tx('span', 'bkbg-fan-badge', o.version, { background: o.versionBg, color: o.versionColor })); |
| 134 |
} |
| 135 |
// Status badge |
| 136 |
var stLabel = statusLabels[o.status] || o.status; |
| 137 |
ap(meta, tx('span', 'bkbg-fan-badge', stLabel, { background: o.statusBg, color: o.statusColor })); |
| 138 |
// Date |
| 139 |
if (o.showDate && o.releaseDate) { |
| 140 |
ap(meta, tx('span', 'bkbg-fan-date', o.releaseDate)); |
| 141 |
} |
| 142 |
ap(inner, meta); |
| 143 |
|
| 144 |
// Feature name |
| 145 |
ap(inner, tx('h2', 'bkbg-fan-name', o.featureName, { |
| 146 |
color: o.featureNameColor |
| 147 |
})); |
| 148 |
|
| 149 |
// Tagline |
| 150 |
if (o.tagline) { |
| 151 |
ap(inner, tx('p', 'bkbg-fan-tagline', o.tagline, { |
| 152 |
color: o.taglineColor |
| 153 |
})); |
| 154 |
} |
| 155 |
|
| 156 |
// Description |
| 157 |
if (o.showDescription && o.description) { |
| 158 |
ap(inner, tx('p', 'bkbg-fan-description', o.description, { |
| 159 |
color: o.textColor |
| 160 |
})); |
| 161 |
} |
| 162 |
|
| 163 |
// Highlights |
| 164 |
if (o.showHighlights && o.highlights && o.highlights.length > 0) { |
| 165 |
var hlWrap = mk('div'); |
| 166 |
var hlLabel = tx('div', 'bkbg-fan-highlights-label', o.highlightsLabel || "What's new", { color: o.accentColor }); |
| 167 |
var hlList = mk('ul', 'bkbg-fan-highlights'); |
| 168 |
o.highlights.forEach(function (h) { |
| 169 |
if (!h) return; |
| 170 |
var li = mk('li', 'bkbg-fan-highlight'); |
| 171 |
var icon = tx('span', 'bkbg-fan-highlight-icon', '✦', { color: o.highlightIconColor }); |
| 172 |
var text = tx('span', '', h, { color: o.textColor }); |
| 173 |
ap(li, icon, text); |
| 174 |
ap(hlList, li); |
| 175 |
}); |
| 176 |
ap(hlWrap, hlLabel, hlList); |
| 177 |
ap(inner, hlWrap); |
| 178 |
} |
| 179 |
|
| 180 |
// Plans |
| 181 |
if (o.showPlans && o.availablePlans && o.availablePlans.length > 0) { |
| 182 |
var plansRow = mk('div', 'bkbg-fan-plans'); |
| 183 |
ap(plansRow, tx('span', 'bkbg-fan-plans-label', (o.plansLabel || 'Available on') + ':')); |
| 184 |
o.availablePlans.forEach(function (plan) { |
| 185 |
if (!plan) return; |
| 186 |
ap(plansRow, tx('span', 'bkbg-fan-plan-badge', plan, { background: o.planBg, color: o.planColor })); |
| 187 |
}); |
| 188 |
ap(inner, plansRow); |
| 189 |
} |
| 190 |
|
| 191 |
// CTAs |
| 192 |
var ctas = mk('div', 'bkbg-fan-ctas'); |
| 193 |
if (o.showCta && o.ctaText) { |
| 194 |
var primaryCta = mk('a', 'bkbg-fan-cta', { |
| 195 |
background: o.ctaBg, |
| 196 |
color: o.ctaColor, |
| 197 |
padding: '11px 22px', |
| 198 |
borderRadius: o.borderRadius + 'px' |
| 199 |
}); |
| 200 |
primaryCta.textContent = o.ctaText; |
| 201 |
primaryCta.href = o.ctaUrl || '#'; |
| 202 |
ap(ctas, primaryCta); |
| 203 |
} |
| 204 |
if (o.showSecondaryCta && o.ctaSecondaryText) { |
| 205 |
var secondaryCta = mk('a', 'bkbg-fan-cta is-secondary', { |
| 206 |
borderColor: o.ctaSecondaryColor, |
| 207 |
color: o.ctaSecondaryColor, |
| 208 |
padding: '9px 22px', |
| 209 |
borderRadius: o.borderRadius + 'px' |
| 210 |
}); |
| 211 |
secondaryCta.textContent = o.ctaSecondaryText; |
| 212 |
secondaryCta.href = o.ctaSecondaryUrl || '#'; |
| 213 |
ap(ctas, secondaryCta); |
| 214 |
} |
| 215 |
if (ctas.children.length > 0) { |
| 216 |
ap(inner, ctas); |
| 217 |
} |
| 218 |
|
| 219 |
ap(block, inner); |
| 220 |
appEl.parentNode.insertBefore(block, appEl); |
| 221 |
appEl.style.display = 'none'; |
| 222 |
}); |
| 223 |
} |
| 224 |
|
| 225 |
if (document.readyState !== 'loading') { init(); } |
| 226 |
else { document.addEventListener('DOMContentLoaded', init); } |
| 227 |
})(); |
| 228 |
|