| 1 |
(function () { |
| 2 |
'use strict'; |
| 3 |
|
| 4 |
var copyIcon = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" width="14" height="14"><path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z"/></svg>'; |
| 5 |
|
| 6 |
var sizeMap = { |
| 7 |
sm: { h: '32px', pad: '0 10px', fs: '12px' }, |
| 8 |
md: { h: '40px', pad: '0 14px', fs: '14px' }, |
| 9 |
lg: { h: '48px', pad: '0 18px', fs: '16px' }, |
| 10 |
}; |
| 11 |
|
| 12 |
var _typoKeys = { |
| 13 |
family:'font-family', weight:'font-weight', style:'font-style', |
| 14 |
transform:'text-transform', decoration:'text-decoration', |
| 15 |
sizeDesktop:'font-size-d', sizeTablet:'font-size-t', sizeMobile:'font-size-m', |
| 16 |
lineHeightDesktop:'line-height-d', lineHeightTablet:'line-height-t', lineHeightMobile:'line-height-m', |
| 17 |
letterSpacingDesktop:'letter-spacing-d', letterSpacingTablet:'letter-spacing-t', letterSpacingMobile:'letter-spacing-m', |
| 18 |
wordSpacingDesktop:'word-spacing-d', wordSpacingTablet:'word-spacing-t', wordSpacingMobile:'word-spacing-m' |
| 19 |
}; |
| 20 |
var _typoUnits = { size:'sizeUnit', lineHeight:'lineHeightUnit', letterSpacing:'letterSpacingUnit', wordSpacing:'wordSpacingUnit' }; |
| 21 |
var _typoUnitDefaults = { size:'px', lineHeight:'', letterSpacing:'px', wordSpacing:'px' }; |
| 22 |
function typoCssVarsForEl(el, obj, prefix) { |
| 23 |
if (!obj || typeof obj !== 'object') return; |
| 24 |
Object.keys(_typoKeys).forEach(function (k) { |
| 25 |
var v = obj[k]; if (v === undefined || v === '') return; |
| 26 |
var prop = _typoKeys[k]; |
| 27 |
var base = k.replace(/Desktop|Tablet|Mobile/, ''); |
| 28 |
var uKey = _typoUnits[base]; |
| 29 |
if (uKey && typeof v === 'number') v = v + (obj[uKey] || _typoUnitDefaults[base] || ''); |
| 30 |
el.style.setProperty(prefix + prop, v); |
| 31 |
}); |
| 32 |
} |
| 33 |
|
| 34 |
function initClipboard(wrap) { |
| 35 |
var d = wrap.dataset; |
| 36 |
var text = d.text || ''; |
| 37 |
var label = d.label || 'Copy'; |
| 38 |
var copied = d.copiedLabel || 'Copied! ✓'; |
| 39 |
var showCode = d.showCode !== '0'; |
| 40 |
var iconOn = d.icon !== '0'; |
| 41 |
var sz = sizeMap[d.size] || sizeMap.md; |
| 42 |
var radius = parseInt(d.radius, 10) || 8; |
| 43 |
var btnBg = d.btnBg || '#111827'; |
| 44 |
var btnColor = d.btnColor || '#ffffff'; |
| 45 |
var codeBg = d.codeBg || '#f3f4f6'; |
| 46 |
var codeColor = d.codeColor || '#111827'; |
| 47 |
var codeFs = (d.codeFs || '16') + 'px'; |
| 48 |
var fw = d.fw || '600'; |
| 49 |
var toast = parseInt(d.toast, 10) || 2000; |
| 50 |
var desc = d.description || ''; |
| 51 |
var descFs = d.descSize || '13'; |
| 52 |
|
| 53 |
/* Apply typography CSS vars */ |
| 54 |
try { var typoCode = JSON.parse(d.typoCode || '{}'); typoCssVarsForEl(wrap, typoCode, '--bkbg-cpc-cd-'); } catch(e){} |
| 55 |
try { var typoDesc = JSON.parse(d.typoDesc || '{}'); typoCssVarsForEl(wrap, typoDesc, '--bkbg-cpc-ds-'); } catch(e){} |
| 56 |
|
| 57 |
/* Apply card styles as CSS vars on wrap */ |
| 58 |
wrap.style.setProperty('--bkbg-cpc-bg', d.bg || '#f9fafb'); |
| 59 |
wrap.style.setProperty('--bkbg-cpc-border', d.border || '#e5e7eb'); |
| 60 |
wrap.style.setProperty('--bkbg-cpc-radius', radius + 'px'); |
| 61 |
|
| 62 |
/* Description */ |
| 63 |
if (desc) { |
| 64 |
var p = document.createElement('p'); |
| 65 |
p.className = 'bkbg-cpc-desc'; |
| 66 |
p.textContent = desc; |
| 67 |
wrap.appendChild(p); |
| 68 |
} |
| 69 |
|
| 70 |
/* Code display */ |
| 71 |
if (showCode && text) { |
| 72 |
var codeEl = document.createElement('span'); |
| 73 |
codeEl.className = 'bkbg-cpc-code'; |
| 74 |
codeEl.textContent = text; |
| 75 |
codeEl.style.cssText = [ |
| 76 |
'background:' + codeBg, |
| 77 |
'color:' + codeColor, |
| 78 |
'border-radius:'+ (radius / 2) + 'px', |
| 79 |
].join(';'); |
| 80 |
wrap.appendChild(codeEl); |
| 81 |
} |
| 82 |
|
| 83 |
/* Button */ |
| 84 |
var btn = document.createElement('button'); |
| 85 |
btn.className = 'bkbg-cpc-btn'; |
| 86 |
btn.type = 'button'; |
| 87 |
btn.style.cssText = [ |
| 88 |
'height:' + sz.h, |
| 89 |
'padding:' + sz.pad, |
| 90 |
'background:' + btnBg, |
| 91 |
'color:' + btnColor, |
| 92 |
'font-size:' + sz.fs, |
| 93 |
'font-weight:' + fw, |
| 94 |
'border-radius:'+ (radius / 2) + 'px', |
| 95 |
].join(';'); |
| 96 |
|
| 97 |
if (iconOn) { |
| 98 |
var iconWrap = document.createElement('span'); |
| 99 |
iconWrap.style.cssText = 'display:flex;align-items:center;'; |
| 100 |
iconWrap.innerHTML = copyIcon; |
| 101 |
btn.appendChild(iconWrap); |
| 102 |
} |
| 103 |
var btnText = document.createElement('span'); |
| 104 |
btnText.textContent = label; |
| 105 |
btn.appendChild(btnText); |
| 106 |
wrap.appendChild(btn); |
| 107 |
|
| 108 |
/* Copy handler */ |
| 109 |
var timeout; |
| 110 |
btn.addEventListener('click', function () { |
| 111 |
clearTimeout(timeout); |
| 112 |
function onSuccess() { |
| 113 |
btnText.textContent = copied; |
| 114 |
btn.style.background = '#10b981'; |
| 115 |
timeout = setTimeout(function () { |
| 116 |
btnText.textContent = label; |
| 117 |
btn.style.background = btnBg; |
| 118 |
}, toast); |
| 119 |
} |
| 120 |
if (navigator.clipboard && navigator.clipboard.writeText) { |
| 121 |
navigator.clipboard.writeText(text).then(onSuccess).catch(function () { |
| 122 |
fallbackCopy(text); |
| 123 |
onSuccess(); |
| 124 |
}); |
| 125 |
} else { |
| 126 |
fallbackCopy(text); |
| 127 |
onSuccess(); |
| 128 |
} |
| 129 |
}); |
| 130 |
} |
| 131 |
|
| 132 |
function fallbackCopy(text) { |
| 133 |
var ta = document.createElement('textarea'); |
| 134 |
ta.value = text; |
| 135 |
ta.style.cssText = 'position:fixed;top:-9999px;left:-9999px;opacity:0;'; |
| 136 |
document.body.appendChild(ta); |
| 137 |
ta.focus(); |
| 138 |
ta.select(); |
| 139 |
try { document.execCommand('copy'); } catch (e) {} |
| 140 |
document.body.removeChild(ta); |
| 141 |
} |
| 142 |
|
| 143 |
document.addEventListener('DOMContentLoaded', function () { |
| 144 |
document.querySelectorAll('.bkbg-cpc-wrap[data-text]').forEach(initClipboard); |
| 145 |
}); |
| 146 |
})(); |
| 147 |
|