| 1 |
(function () { |
| 2 |
function isBright(hex) { |
| 3 |
if (!hex || hex.length < 7) return true; |
| 4 |
var r = parseInt(hex.slice(1, 3), 16); |
| 5 |
var g = parseInt(hex.slice(3, 5), 16); |
| 6 |
var b = parseInt(hex.slice(5, 7), 16); |
| 7 |
return (r * 299 + g * 587 + b * 114) / 1000 > 180; |
| 8 |
} |
| 9 |
|
| 10 |
function copyText(text, btn) { |
| 11 |
if (navigator.clipboard) { |
| 12 |
navigator.clipboard.writeText(text).then(function () { |
| 13 |
btn.textContent = 'Copied!'; |
| 14 |
btn.classList.add('copied'); |
| 15 |
setTimeout(function () { |
| 16 |
btn.textContent = 'copy'; |
| 17 |
btn.classList.remove('copied'); |
| 18 |
}, 1400); |
| 19 |
}); |
| 20 |
} else { |
| 21 |
var ta = document.createElement('textarea'); |
| 22 |
ta.value = text; |
| 23 |
ta.style.position = 'fixed'; |
| 24 |
ta.style.opacity = '0'; |
| 25 |
document.body.appendChild(ta); |
| 26 |
ta.select(); |
| 27 |
document.execCommand('copy'); |
| 28 |
document.body.removeChild(ta); |
| 29 |
btn.textContent = 'Copied!'; |
| 30 |
btn.classList.add('copied'); |
| 31 |
setTimeout(function () { |
| 32 |
btn.textContent = 'copy'; |
| 33 |
btn.classList.remove('copied'); |
| 34 |
}, 1400); |
| 35 |
} |
| 36 |
} |
| 37 |
|
| 38 |
function typoCssVarsForEl(typo, prefix, el) { |
| 39 |
if (!typo) return; |
| 40 |
if (typo.family) el.style.setProperty(prefix + 'font-family', "'" + typo.family + "', sans-serif"); |
| 41 |
if (typo.weight) el.style.setProperty(prefix + 'font-weight', typo.weight); |
| 42 |
if (typo.transform) el.style.setProperty(prefix + 'text-transform', typo.transform); |
| 43 |
if (typo.style) el.style.setProperty(prefix + 'font-style', typo.style); |
| 44 |
if (typo.decoration) el.style.setProperty(prefix + 'text-decoration', typo.decoration); |
| 45 |
var su = typo.sizeUnit || 'px'; |
| 46 |
if (typo.sizeDesktop !== '' && typo.sizeDesktop != null) el.style.setProperty(prefix + 'font-size-d', typo.sizeDesktop + su); |
| 47 |
if (typo.sizeTablet !== '' && typo.sizeTablet != null) el.style.setProperty(prefix + 'font-size-t', typo.sizeTablet + su); |
| 48 |
if (typo.sizeMobile !== '' && typo.sizeMobile != null) el.style.setProperty(prefix + 'font-size-m', typo.sizeMobile + su); |
| 49 |
var lhu = typo.lineHeightUnit || ''; |
| 50 |
if (typo.lineHeightDesktop !== '' && typo.lineHeightDesktop != null) el.style.setProperty(prefix + 'line-height-d', typo.lineHeightDesktop + lhu); |
| 51 |
if (typo.lineHeightTablet !== '' && typo.lineHeightTablet != null) el.style.setProperty(prefix + 'line-height-t', typo.lineHeightTablet + lhu); |
| 52 |
if (typo.lineHeightMobile !== '' && typo.lineHeightMobile != null) el.style.setProperty(prefix + 'line-height-m', typo.lineHeightMobile + lhu); |
| 53 |
var lsu = typo.letterSpacingUnit || 'px'; |
| 54 |
if (typo.letterSpacingDesktop !== '' && typo.letterSpacingDesktop != null) el.style.setProperty(prefix + 'letter-spacing-d', typo.letterSpacingDesktop + lsu); |
| 55 |
if (typo.letterSpacingTablet !== '' && typo.letterSpacingTablet != null) el.style.setProperty(prefix + 'letter-spacing-t', typo.letterSpacingTablet + lsu); |
| 56 |
if (typo.letterSpacingMobile !== '' && typo.letterSpacingMobile != null) el.style.setProperty(prefix + 'letter-spacing-m', typo.letterSpacingMobile + lsu); |
| 57 |
var wsu = typo.wordSpacingUnit || 'px'; |
| 58 |
if (typo.wordSpacingDesktop !== '' && typo.wordSpacingDesktop != null) el.style.setProperty(prefix + 'word-spacing-d', typo.wordSpacingDesktop + wsu); |
| 59 |
if (typo.wordSpacingTablet !== '' && typo.wordSpacingTablet != null) el.style.setProperty(prefix + 'word-spacing-t', typo.wordSpacingTablet + wsu); |
| 60 |
if (typo.wordSpacingMobile !== '' && typo.wordSpacingMobile != null) el.style.setProperty(prefix + 'word-spacing-m', typo.wordSpacingMobile + wsu); |
| 61 |
} |
| 62 |
|
| 63 |
function init() { |
| 64 |
document.querySelectorAll('.bkbg-bk-app').forEach(function (appEl) { |
| 65 |
if (appEl.dataset.rendered) return; |
| 66 |
appEl.dataset.rendered = '1'; |
| 67 |
|
| 68 |
var opts; |
| 69 |
try { opts = JSON.parse(appEl.dataset.opts || '{}'); } catch (e) { opts = {}; } |
| 70 |
var o = Object.assign({ |
| 71 |
sectionTitle: 'Brand Identity', |
| 72 |
showTitle: true, |
| 73 |
showColors: true, |
| 74 |
colorsTitle: 'Colour Palette', |
| 75 |
colors: [], |
| 76 |
showCopyHint: true, |
| 77 |
swatchRadius: 10, |
| 78 |
swatchHeight: 90, |
| 79 |
showColorName: true, |
| 80 |
showColorHex: true, |
| 81 |
showTypography: true, |
| 82 |
typographyTitle: 'Typography', |
| 83 |
fonts: [], |
| 84 |
showLogos: true, |
| 85 |
logosTitle: 'Logo Usage', |
| 86 |
logos: [], |
| 87 |
showValues: true, |
| 88 |
valuesTitle: 'Brand Values', |
| 89 |
values: [], |
| 90 |
maxWidth: 1000, |
| 91 |
containerPadding: 48, |
| 92 |
sectionGap: 56, |
| 93 |
cardRadius: 12, |
| 94 |
cardPadding: 28, |
| 95 |
containerBg: '', |
| 96 |
cardBg: '#ffffff', |
| 97 |
cardBorder: '#e5e7eb', |
| 98 |
headingColor: '#111827', |
| 99 |
textColor: '#374151', |
| 100 |
sectionLabelColor: '#6366f1', |
| 101 |
sectionLabelBg: '#ede9fe', |
| 102 |
valueIconBg: '#f5f3ff', |
| 103 |
}, opts); |
| 104 |
|
| 105 |
// Build root |
| 106 |
var wrap = document.createElement('div'); |
| 107 |
wrap.className = 'bkbg-bk-wrap'; |
| 108 |
if (o.containerBg) wrap.style.background = o.containerBg; |
| 109 |
wrap.style.paddingTop = o.containerPadding + 'px'; |
| 110 |
wrap.style.paddingBottom = o.containerPadding + 'px'; |
| 111 |
|
| 112 |
var inner = document.createElement('div'); |
| 113 |
inner.className = 'bkbg-bk-inner'; |
| 114 |
inner.style.maxWidth = o.maxWidth + 'px'; |
| 115 |
wrap.appendChild(inner); |
| 116 |
|
| 117 |
function makeSection(title) { |
| 118 |
var sec = document.createElement('div'); |
| 119 |
sec.className = 'bkbg-bk-section'; |
| 120 |
sec.style.background = o.cardBg; |
| 121 |
sec.style.borderColor = o.cardBorder; |
| 122 |
sec.style.borderRadius = o.cardRadius + 'px'; |
| 123 |
sec.style.padding = o.cardPadding + 'px'; |
| 124 |
sec.style.marginBottom = o.sectionGap + 'px'; |
| 125 |
|
| 126 |
var label = document.createElement('div'); |
| 127 |
label.className = 'bkbg-bk-label'; |
| 128 |
label.style.background = o.sectionLabelBg; |
| 129 |
label.style.color = o.sectionLabelColor; |
| 130 |
label.textContent = title; |
| 131 |
sec.appendChild(label); |
| 132 |
|
| 133 |
return sec; |
| 134 |
} |
| 135 |
|
| 136 |
// Main title |
| 137 |
if (o.showTitle && o.sectionTitle) { |
| 138 |
var title = document.createElement('h2'); |
| 139 |
title.className = 'bkbg-bk-main-title'; |
| 140 |
title.style.color = o.headingColor; |
| 141 |
title.style.marginBottom = o.sectionGap + 'px'; |
| 142 |
title.textContent = o.sectionTitle; |
| 143 |
inner.appendChild(title); |
| 144 |
} |
| 145 |
|
| 146 |
// ── Colour palette ── |
| 147 |
if (o.showColors && o.colors && o.colors.length) { |
| 148 |
var colorSec = makeSection(o.colorsTitle); |
| 149 |
var colorGrid = document.createElement('div'); |
| 150 |
colorGrid.className = 'bkbg-bk-colors-grid'; |
| 151 |
|
| 152 |
o.colors.forEach(function (clr) { |
| 153 |
var bright = isBright(clr.value); |
| 154 |
|
| 155 |
var swatchWrap = document.createElement('div'); |
| 156 |
swatchWrap.className = 'bkbg-bk-swatch-wrap'; |
| 157 |
|
| 158 |
var swatch = document.createElement('div'); |
| 159 |
swatch.className = 'bkbg-bk-swatch'; |
| 160 |
swatch.style.height = o.swatchHeight + 'px'; |
| 161 |
swatch.style.background = clr.value; |
| 162 |
swatch.style.borderRadius = o.swatchRadius + 'px'; |
| 163 |
if (bright) swatch.style.border = '1px solid #e5e7eb'; |
| 164 |
|
| 165 |
if (o.showCopyHint) { |
| 166 |
var copyBtn = document.createElement('span'); |
| 167 |
copyBtn.className = 'bkbg-bk-swatch-copy'; |
| 168 |
copyBtn.textContent = 'copy'; |
| 169 |
copyBtn.style.background = bright ? 'rgba(0,0,0,0.08)' : 'rgba(0,0,0,0.25)'; |
| 170 |
copyBtn.style.color = bright ? '#374151' : 'rgba(255,255,255,0.9)'; |
| 171 |
swatch.appendChild(copyBtn); |
| 172 |
|
| 173 |
swatch.addEventListener('click', function () { |
| 174 |
copyText(clr.value, copyBtn); |
| 175 |
}); |
| 176 |
} |
| 177 |
|
| 178 |
swatchWrap.appendChild(swatch); |
| 179 |
|
| 180 |
if (o.showColorName) { |
| 181 |
var nameEl = document.createElement('div'); |
| 182 |
nameEl.className = 'bkbg-bk-color-name'; |
| 183 |
nameEl.style.color = o.headingColor; |
| 184 |
nameEl.style.marginTop = '6px'; |
| 185 |
nameEl.textContent = clr.name; |
| 186 |
swatchWrap.appendChild(nameEl); |
| 187 |
} |
| 188 |
if (o.showColorHex) { |
| 189 |
var hexEl = document.createElement('div'); |
| 190 |
hexEl.className = 'bkbg-bk-color-hex'; |
| 191 |
hexEl.style.color = o.textColor; |
| 192 |
hexEl.textContent = clr.value; |
| 193 |
swatchWrap.appendChild(hexEl); |
| 194 |
} |
| 195 |
|
| 196 |
colorGrid.appendChild(swatchWrap); |
| 197 |
}); |
| 198 |
|
| 199 |
colorSec.appendChild(colorGrid); |
| 200 |
inner.appendChild(colorSec); |
| 201 |
} |
| 202 |
|
| 203 |
// ── Typography ── |
| 204 |
if (o.showTypography && o.fonts && o.fonts.length) { |
| 205 |
var typeSec = makeSection(o.typographyTitle); |
| 206 |
var fontsWrap = document.createElement('div'); |
| 207 |
fontsWrap.className = 'bkbg-bk-fonts'; |
| 208 |
|
| 209 |
o.fonts.forEach(function (font, i) { |
| 210 |
var fontItem = document.createElement('div'); |
| 211 |
fontItem.className = 'bkbg-bk-font-item'; |
| 212 |
|
| 213 |
// Meta row |
| 214 |
var metaRow = document.createElement('div'); |
| 215 |
metaRow.className = 'bkbg-bk-font-meta'; |
| 216 |
|
| 217 |
var metaLeft = document.createElement('div'); |
| 218 |
var labelEl = document.createElement('div'); |
| 219 |
labelEl.className = 'bkbg-bk-font-label'; |
| 220 |
labelEl.style.color = o.sectionLabelColor; |
| 221 |
labelEl.textContent = font.name; |
| 222 |
var infoEl = document.createElement('div'); |
| 223 |
infoEl.className = 'bkbg-bk-font-info'; |
| 224 |
infoEl.style.color = o.textColor; |
| 225 |
infoEl.textContent = font.familyName + (font.weights ? ' · ' + font.weights : ''); |
| 226 |
metaLeft.appendChild(labelEl); |
| 227 |
metaLeft.appendChild(infoEl); |
| 228 |
metaRow.appendChild(metaLeft); |
| 229 |
|
| 230 |
if (font.sourceUrl) { |
| 231 |
var srcLink = document.createElement('a'); |
| 232 |
srcLink.className = 'bkbg-bk-font-link'; |
| 233 |
srcLink.href = font.sourceUrl; |
| 234 |
srcLink.target = '_blank'; |
| 235 |
srcLink.rel = 'noopener noreferrer'; |
| 236 |
srcLink.style.color = o.sectionLabelColor; |
| 237 |
srcLink.textContent = 'View font →'; |
| 238 |
metaRow.appendChild(srcLink); |
| 239 |
} |
| 240 |
|
| 241 |
fontItem.appendChild(metaRow); |
| 242 |
|
| 243 |
// Heading specimen |
| 244 |
if (font.headingText) { |
| 245 |
var headEl = document.createElement('p'); |
| 246 |
headEl.className = 'bkbg-bk-font-heading'; |
| 247 |
headEl.style.fontFamily = font.cssFamily; |
| 248 |
headEl.style.color = o.headingColor; |
| 249 |
headEl.textContent = font.headingText; |
| 250 |
fontItem.appendChild(headEl); |
| 251 |
} |
| 252 |
|
| 253 |
// Body specimen |
| 254 |
if (font.bodyText) { |
| 255 |
var bodyEl = document.createElement('p'); |
| 256 |
bodyEl.className = 'bkbg-bk-font-body'; |
| 257 |
bodyEl.style.fontFamily = font.cssFamily; |
| 258 |
bodyEl.style.color = o.textColor; |
| 259 |
bodyEl.textContent = font.bodyText; |
| 260 |
fontItem.appendChild(bodyEl); |
| 261 |
} |
| 262 |
|
| 263 |
fontsWrap.appendChild(fontItem); |
| 264 |
}); |
| 265 |
|
| 266 |
typeSec.appendChild(fontsWrap); |
| 267 |
inner.appendChild(typeSec); |
| 268 |
} |
| 269 |
|
| 270 |
// ── Logos ── |
| 271 |
if (o.showLogos && o.logos && o.logos.length) { |
| 272 |
var logoSec = makeSection(o.logosTitle); |
| 273 |
var logosGrid = document.createElement('div'); |
| 274 |
logosGrid.className = 'bkbg-bk-logos-grid'; |
| 275 |
|
| 276 |
o.logos.forEach(function (logo) { |
| 277 |
var logoCard = document.createElement('div'); |
| 278 |
logoCard.className = 'bkbg-bk-logo-card'; |
| 279 |
|
| 280 |
var logoBg = document.createElement('div'); |
| 281 |
logoBg.className = 'bkbg-bk-logo-bg'; |
| 282 |
|
| 283 |
var bgColor = logo.bgStyle === 'dark' ? '#0f172a' |
| 284 |
: logo.bgStyle === 'light' ? '#f8fafc' |
| 285 |
: 'transparent'; |
| 286 |
|
| 287 |
if (logo.bgStyle === 'transparent') { |
| 288 |
logoBg.style.backgroundImage = 'repeating-conic-gradient(#e5e7eb 0% 25%, #fff 0% 50%)'; |
| 289 |
logoBg.style.backgroundSize = '20px 20px'; |
| 290 |
} else { |
| 291 |
logoBg.style.background = bgColor; |
| 292 |
} |
| 293 |
|
| 294 |
if (logo.imageUrl) { |
| 295 |
var logoImg = document.createElement('img'); |
| 296 |
logoImg.src = logo.imageUrl; |
| 297 |
logoImg.alt = logo.imageAlt || ''; |
| 298 |
logoBg.appendChild(logoImg); |
| 299 |
} else { |
| 300 |
logoBg.style.color = '#9ca3af'; |
| 301 |
logoBg.style.fontSize = '13px'; |
| 302 |
logoBg.textContent = '(no logo uploaded)'; |
| 303 |
} |
| 304 |
|
| 305 |
logoCard.appendChild(logoBg); |
| 306 |
|
| 307 |
if (logo.label) { |
| 308 |
var logoLabel = document.createElement('div'); |
| 309 |
logoLabel.className = 'bkbg-bk-logo-label'; |
| 310 |
logoLabel.style.color = o.headingColor; |
| 311 |
logoLabel.textContent = logo.label; |
| 312 |
logoCard.appendChild(logoLabel); |
| 313 |
} |
| 314 |
|
| 315 |
if (logo.description) { |
| 316 |
var logoDesc = document.createElement('div'); |
| 317 |
logoDesc.className = 'bkbg-bk-logo-desc'; |
| 318 |
logoDesc.style.color = o.textColor; |
| 319 |
logoDesc.textContent = logo.description; |
| 320 |
logoCard.appendChild(logoDesc); |
| 321 |
} |
| 322 |
|
| 323 |
logosGrid.appendChild(logoCard); |
| 324 |
}); |
| 325 |
|
| 326 |
logoSec.appendChild(logosGrid); |
| 327 |
inner.appendChild(logoSec); |
| 328 |
} |
| 329 |
|
| 330 |
// ── Brand Values ── |
| 331 |
if (o.showValues && o.values && o.values.length) { |
| 332 |
var valuesSec = makeSection(o.valuesTitle); |
| 333 |
valuesSec.style.marginBottom = '0'; |
| 334 |
var valuesGrid = document.createElement('div'); |
| 335 |
valuesGrid.className = 'bkbg-bk-values-grid'; |
| 336 |
|
| 337 |
o.values.forEach(function (val) { |
| 338 |
var valueEl = document.createElement('div'); |
| 339 |
valueEl.className = 'bkbg-bk-value'; |
| 340 |
|
| 341 |
var iconEl = document.createElement('div'); |
| 342 |
iconEl.className = 'bkbg-bk-value-icon'; |
| 343 |
iconEl.style.background = o.valueIconBg; |
| 344 |
var _IP = window.bkbgIconPicker; |
| 345 |
var _iType = val.iconType || 'custom-char'; |
| 346 |
if (_IP && _iType !== 'custom-char') { |
| 347 |
var _in = _IP.buildFrontendIcon(_iType, val.icon, val.iconDashicon, val.iconImageUrl, val.iconDashiconColor); |
| 348 |
if (_in) iconEl.appendChild(_in); |
| 349 |
else iconEl.textContent = val.icon; |
| 350 |
} else { |
| 351 |
iconEl.textContent = val.icon; |
| 352 |
} |
| 353 |
valueEl.appendChild(iconEl); |
| 354 |
|
| 355 |
var titleEl = document.createElement('h4'); |
| 356 |
titleEl.className = 'bkbg-bk-value-title'; |
| 357 |
titleEl.style.color = o.headingColor; |
| 358 |
titleEl.textContent = val.title; |
| 359 |
valueEl.appendChild(titleEl); |
| 360 |
|
| 361 |
if (val.description) { |
| 362 |
var descEl = document.createElement('p'); |
| 363 |
descEl.className = 'bkbg-bk-value-desc'; |
| 364 |
descEl.style.color = o.textColor; |
| 365 |
descEl.textContent = val.description; |
| 366 |
valueEl.appendChild(descEl); |
| 367 |
} |
| 368 |
|
| 369 |
valuesGrid.appendChild(valueEl); |
| 370 |
}); |
| 371 |
|
| 372 |
valuesSec.appendChild(valuesGrid); |
| 373 |
inner.appendChild(valuesSec); |
| 374 |
} |
| 375 |
|
| 376 |
typoCssVarsForEl(opts.typoTitle, '--bkbg-bdk-title-', wrap); |
| 377 |
typoCssVarsForEl(opts.typoBody, '--bkbg-bdk-body-', wrap); |
| 378 |
|
| 379 |
appEl.parentNode.insertBefore(wrap, appEl); |
| 380 |
appEl.style.display = 'none'; |
| 381 |
}); |
| 382 |
} |
| 383 |
|
| 384 |
if (document.readyState !== 'loading') { init(); } |
| 385 |
else { document.addEventListener('DOMContentLoaded', init); } |
| 386 |
})(); |
| 387 |
|