window.xtermToRGB = function(idx) { idx = parseInt(idx); if (idx < 0 || idx > 255) return [0,0,0]; if (idx < 16) { var a = [[0,0,0],[170,0,0],[0,170,0],[170,170,0],[0,0,170],[170,0,170],[0,170,170],[170,170,170], [85,85,85],[255,85,85],[85,255,85],[255,255,85],[85,85,255],[255,85,255],[85,255,255],[255,255,255]]; return a[idx]; } if (idx < 232) { var n = idx - 16; var cube = [0,95,135,175,215,255]; return [cube[Math.floor(n/36)], cube[Math.floor((n%36)/6)], cube[n%6]]; } var g = 8 + (idx-232)*10; return [g,g,g]; }; window.xtermIdxToHex = function(idx) { idx = parseInt(idx) || 0; return idx.toString(16).toUpperCase().padStart(2,'0'); }; window.hexToXtermIdx = function(hex) { return parseInt(hex, 16); }; window.xtermToCss = function(idx) { var rgb = xtermToRGB(idx); return '#' + ((rgb[0]<<16)|(rgb[1]<<8)|rgb[2]).toString(16).padStart(6,'0').toUpperCase(); }; window.resolveColor = function(v) { if (!v) return '#3a3a6a'; v = v.toUpperCase().replace(/[^0-9A-F]/g,''); if (v.length === 2) return xtermToCss(parseInt(v,16)); return '#' + v.substring(0,6).padEnd(6,'0'); }; window.hexLuminance = function(hex) { hex = hex.replace('#','').toUpperCase(); var r = parseInt(hex.substring(0,2),16)/255; var g = parseInt(hex.substring(2,4),16)/255; var b = parseInt(hex.substring(4,6),16)/255; return 0.299*r + 0.587*g + 0.114*b; }; window.cssToXtermIdx = function(css) { css = css.replace('#','').toUpperCase(); if (css.length < 6) return 0; var tr = parseInt(css.substring(0,2),16); var tg = parseInt(css.substring(2,4),16); var tb = parseInt(css.substring(4,6),16); var best = 0, bestDist = Infinity; for (var i = 0; i < 256; i++) { var srgb = xtermToRGB(i); var dr = tr-srgb[0], dg = tg-srgb[1], db = tb-srgb[2]; var d = dr*dr + dg*dg + db*db; if (d < bestDist) { bestDist = d; best = i; } } return best; }; (function() { var pickerEl = null, boundInput = null, boundSwatch = null; window._colorPickerActive = false; function ensurePicker() { if (pickerEl) return; pickerEl = document.createElement('div'); pickerEl.id = '__cp_popover'; pickerEl.style.cssText = 'display:none;position:fixed;z-index:200;background:var(--panel);border:1px solid var(--border);border-radius:6px;padding:8px;box-shadow:0 4px 20px rgba(0,0,0,.5);min-width:280px'; pickerEl.innerHTML = buildPickerHTML(); document.body.appendChild(pickerEl); pickerEl.addEventListener('click', function(e) { var sw = e.target.closest('.cp-swatch'); if (sw) { var idx = parseInt(sw.getAttribute('data-idx')); var hex = xtermIdxToHex(idx); if (boundInput) boundInput.value = hex; if (boundSwatch) boundSwatch.style.background = xtermToCss(idx); if (boundInput) boundInput.dispatchEvent(new Event('input', {bubbles:true})); hidePicker(); } }); } function buildPickerHTML() { var h = '
'; h += ''; h += ''; h += ''; h += '
'; h += '
'; for (var i = 0; i < 256; i++) { var css = xtermToCss(i); h += '
'; } h += '
'; return h; } window.showColorPicker = function(inputEl, swatchEl) { ensurePicker(); boundInput = inputEl; boundSwatch = swatchEl; var raw = (inputEl.value || '').toUpperCase().replace(/[^0-9A-F]/g,''); var idx; if (raw.length === 2) { idx = parseInt(raw, 16); } else if (raw.length >= 6) { idx = cssToXtermIdx(raw); } else { idx = parseInt(raw, 16) || 0; } var hex = xtermIdxToHex(idx); window._colorPickerActive = true; inputEl.value = hex; if (swatchEl) swatchEl.style.background = xtermToCss(idx); $('#__cp_hex').value = hex; $('#__cp_preview').style.background = xtermToCss(idx); updatePickerSelection(idx); var rect = inputEl.getBoundingClientRect(); pickerEl.style.display = 'block'; var pw = pickerEl.offsetWidth; var left = rect.left; if (left + pw > window.innerWidth - 10) left = Math.max(10, window.innerWidth - pw - 10); pickerEl.style.left = left + 'px'; pickerEl.style.top = (rect.bottom + 4) + 'px'; $('#__cp_hex').oninput = function() { var v = this.value.toUpperCase().replace(/[^0-9A-F]/g,'').substring(0,2); this.value = v; if (v.length === 2) { var i = parseInt(v, 16); inputEl.value = v; if (swatchEl) swatchEl.style.background = xtermToCss(i); updatePickerSelection(i); } }; $('#__cp_close').onclick = hidePicker; }; function updatePickerSelection(idx) { var swatches = document.querySelectorAll('.cp-swatch'); for (var i = 0; i < swatches.length; i++) swatches[i].classList.remove('selected'); var s = document.querySelector('.cp-swatch[data-idx="'+idx+'"]'); if (s) s.classList.add('selected'); } window.hideColorPicker = hidePicker; function hidePicker() { if (pickerEl) pickerEl.style.display = 'none'; var input = boundInput; boundInput = null; boundSwatch = null; window._colorPickerActive = false; if (input && input.isConnected) { input.dispatchEvent(new Event('input', {bubbles:true})); } } document.addEventListener('click', function(e) { if (!pickerEl || pickerEl.style.display === 'none') return; if (!pickerEl.contains(e.target) && e.target !== boundInput && e.target !== (boundSwatch || {}).parentElement) { hidePicker(); } }); window.bindColorField = function(fieldEl) { var input = fieldEl.querySelector('input[type=text]') || fieldEl.querySelector('input:not([type])'); var swatch = fieldEl.querySelector('.color-swatch'); if (!input) return; fieldEl.addEventListener('click', function(e) { if (e.target === input || e.target === swatch) { showColorPicker(input, swatch); } }); var raw = (input.value || '').toUpperCase().replace(/[^0-9A-F]/g,''); if (raw.length === 2) { if (swatch) swatch.style.background = xtermToCss(parseInt(raw, 16)); } else if (raw.length >= 6) { var idx = cssToXtermIdx(raw); input.value = xtermIdxToHex(idx); if (swatch) swatch.style.background = xtermToCss(idx); } input.addEventListener('input', function() { var v = this.value.toUpperCase().replace(/[^0-9A-F]/g,'').substring(0,2); this.value = v; if (v.length === 2 && swatch) { swatch.style.background = xtermToCss(parseInt(v, 16)); } }); input.setAttribute('maxlength', '2'); input.setAttribute('placeholder', '00'); input.style.textTransform = 'uppercase'; }; })();