diff options
| author | historia <[not public]> | 2026-07-15 06:19:05 -0400 |
|---|---|---|
| committer | historia <[not public]> | 2026-07-15 06:19:05 -0400 |
| commit | e09e7badbc722f580a9d7674c46d6ff3cc320b26 (patch) | |
| tree | a6beb1ed8a2ed3e2ae2334a619a1e0b40e5030d6 /internal/admin/static | |
| parent | 84dd8c7557d8b9d92cd8d339afc28a0fd9a3a896 (diff) | |
| download | thehouseoficarus-e09e7badbc722f580a9d7674c46d6ff3cc320b26.tar.gz | |
feat(admin): color picker shows color cube correctly
Diffstat (limited to 'internal/admin/static')
| -rw-r--r-- | internal/admin/static/admin.css | 11 | ||||
| -rw-r--r-- | internal/admin/static/coloreditor.js | 45 | ||||
| -rw-r--r-- | internal/admin/static/colorpicker.js | 35 |
3 files changed, 72 insertions, 19 deletions
diff --git a/internal/admin/static/admin.css b/internal/admin/static/admin.css index 06a640c..d1d3c4d 100644 --- a/internal/admin/static/admin.css +++ b/internal/admin/static/admin.css @@ -182,7 +182,13 @@ details.dir-group summary.dir-header::-webkit-details-marker{display:none} .form-grid .form-group textarea{font-size:11px;padding:4px 6px;min-height:40px} .form-grid .form-group.full{grid-column:1/-1} .form-grid .form-group.full textarea{min-height:60px} -.cp-grid{display:grid;grid-template-columns:repeat(16,1fr);gap:2px} +.cp-grid{display:grid;gap:2px} +.cp-grid.cp-ansi{grid-template-columns:repeat(8,1fr);width:192px} +.cp-grid.cp-cube{grid-template-columns:repeat(6,1fr)} +.cp-grid.cp-gray{grid-template-columns:repeat(12,1fr);width:192px} +.cp-cube-row{display:flex;flex-wrap:wrap;gap:4px;margin:4px 0;width:192px} +.cp-section-label{font-size:10px;color:#888;margin-top:6px;margin-bottom:2px;text-transform:uppercase;letter-spacing:.5px} +.cp-section-label:first-child{margin-top:0} .cp-swatch{aspect-ratio:1;border:1px solid rgba(255,255,255,.15);cursor:pointer;border-radius:2px;min-width:14px} .cp-swatch:hover{transform:scale(1.3);z-index:1;border-color:#fff} .cp-swatch.selected{outline:2px solid #fff;outline-offset:1px;z-index:1} @@ -522,9 +528,8 @@ input:focus-visible,select:focus-visible,textarea:focus-visible,button:focus-vis .color-preview-toolbar select{padding:3px 6px;background:var(--input-bg);color:var(--text);border:1px solid var(--input-border);border-radius:3px;font-family:monospace} .color-preview-hint{font-size:11px;color:#888} .color-preview-scroll{flex:1;overflow-y:auto;overflow-x:auto;border:1px solid var(--border);border-radius:4px} -.color-preview-pre{margin:0;padding:8px;font-family:ui-monospace,"Cascadia Mono","Cascadia Code","JetBrains Mono","Fira Code",Menlo,Consolas,"DejaVu Sans Mono","Courier New",monospace;font-size:12px;line-height:1;white-space:pre-wrap;color:#e0e0e0;background:#000} +pre.color-preview-pre{margin:0;padding:8px;font-family:ui-monospace,"Cascadia Mono","Cascadia Code","JetBrains Mono","Fira Code",Menlo,Consolas,"DejaVu Sans Mono","Courier New",monospace;font-size:12px;line-height:1;white-space:pre-wrap;color:#e0e0e0;background:#000} .cp-title{color:#9ab;display:block;margin:8px 0 3px 0;font-size:11px;text-transform:uppercase;letter-spacing:.5px;font-weight:bold} .cp-title:first-child{margin-top:0} /* Picker popup tweaks for the themer (richer than bindColorField's) */ -#__cp_popover .cp-grid .cp-swatch{width:14px;height:14px} #__cp_popover .cp-swatch.selected{outline:2px solid #fff;outline-offset:1px} diff --git a/internal/admin/static/coloreditor.js b/internal/admin/static/coloreditor.js index dc219f6..deb7336 100644 --- a/internal/admin/static/coloreditor.js +++ b/internal/admin/static/coloreditor.js @@ -268,11 +268,19 @@ // ── Picker popover (per-row, does not touch bold/dim/bg) ──────────────── var popover = null, boundRow = null, boundCat = null, boundSwatch = null; + function makeSwatch(idx) { + var sw = el('div', 'cp-swatch'); + sw.dataset.idx = idx; + sw.style.background = window.xtermToCss ? xtermToCss(idx) : '#000'; + sw.title = ('0' + idx.toString(16)).slice(-2).toUpperCase() + ' (' + idx + ')'; + return sw; + } + function ensurePicker() { if (popover) return; popover = el('div'); popover.id = '__ct_popover'; - popover.style.cssText = 'display:none;position:fixed;z-index:300;background:var(--panel);border:1px solid var(--border);border-radius:6px;padding:8px;box-shadow:0 4px 20px rgba(0,0,0,.6);max-width:340px'; + popover.style.cssText = 'display:none;position:fixed;z-index:300;background:var(--panel);border:1px solid var(--border);border-radius:6px;padding:8px;box-shadow:0 4px 20px rgba(0,0,0,.6);max-width:400px'; var head = el('div'); head.style.cssText = 'display:flex;align-items:center;gap:6px;margin-bottom:6px'; head.appendChild(el('span', 'color-swatch')); var hexIn = el('input'); hexIn.type = 'text'; hexIn.maxLength = 2; @@ -282,22 +290,33 @@ head.appendChild(hexIn); head.appendChild(offB); head.appendChild(xB); popover.appendChild(head); - var grid = el('div', 'cp-grid'); - for (var i = 0; i < 256; i++) { - var sw = el('div', 'cp-swatch'); - sw.className = 'cp-swatch'; - (function (idx, ee) { - ee.style.background = window.xtermToCss ? xtermToCss(idx) : '#000'; - ee.dataset.idx = idx; - ee.title = ('0' + idx.toString(16)).slice(-2).toUpperCase() + ' (' + idx + ')'; - })(i, sw); - grid.appendChild(sw); + // ANSI colors 0-15 (2 rows of 8) + popover.appendChild(el('div', 'cp-section-label', 'ANSI')); + var ansiGrid = el('div', 'cp-grid cp-ansi'); + for (var i = 0; i < 16; i++) ansiGrid.appendChild(makeSwatch(i)); + popover.appendChild(ansiGrid); + + // Color cube 16-231: six 6x6 slices (G=rows, B=cols, each slice one R level) + popover.appendChild(el('div', 'cp-section-label', 'Color Cube')); + var cubeRow = el('div', 'cp-cube-row'); + for (var r = 0; r < 6; r++) { + var cubeGrid = el('div', 'cp-grid cp-cube'); + for (var g = 0; g < 6; g++) + for (var b = 0; b < 6; b++) + cubeGrid.appendChild(makeSwatch(16 + 36 * r + 6 * g + b)); + cubeRow.appendChild(cubeGrid); } - popover.appendChild(grid); + popover.appendChild(cubeRow); + + // Grayscale 232-255 (2 rows of 12) + popover.appendChild(el('div', 'cp-section-label', 'Grayscale')); + var grayGrid = el('div', 'cp-grid cp-gray'); + for (var i = 232; i < 256; i++) grayGrid.appendChild(makeSwatch(i)); + popover.appendChild(grayGrid); document.body.appendChild(popover); - grid.addEventListener('click', function (e) { + popover.addEventListener('click', function (e) { var s = e.target.closest('.cp-swatch'); if (!s) return; var idx = parseInt(s.dataset.idx, 10); setRowFg(boundRow, boundCat, idx); diff --git a/internal/admin/static/colorpicker.js b/internal/admin/static/colorpicker.js index bba438e..f93b261 100644 --- a/internal/admin/static/colorpicker.js +++ b/internal/admin/static/colorpicker.js @@ -68,7 +68,7 @@ window.cssToXtermIdx = function(css) { 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.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:208px'; pickerEl.innerHTML = buildPickerHTML(); document.body.appendChild(pickerEl); @@ -91,12 +91,41 @@ window.cssToXtermIdx = function(css) { h += '<input id="__cp_hex" style="flex:1;padding:3px 6px;font-size:11px;background:var(--input-bg);color:var(--text);border:1px solid var(--input-border);border-radius:3px;font-family:monospace;text-transform:uppercase" maxlength="2" placeholder="00">'; h += '<button id="__cp_close" style="background:none;border:none;color:#aaa;cursor:pointer;font-size:14px;padding:0 4px">×</button>'; h += '</div>'; - h += '<div class="cp-grid">'; - for (var i = 0; i < 256; i++) { + + // ANSI colors 0-15 (2 rows of 8) + h += '<div class="cp-section-label">ANSI</div>'; + h += '<div class="cp-grid cp-ansi">'; + for (var i = 0; i < 16; i++) { var css = xtermToCss(i); h += '<div class="cp-swatch" data-idx="'+i+'" style="background:'+css+'" title="'+xtermIdxToHex(i)+' ('+i+')"></div>'; } h += '</div>'; + + // Color cube 16-231: six 6x6 slices (G=rows, B=cols, each slice is one R level) + h += '<div class="cp-section-label">Color Cube</div>'; + h += '<div class="cp-cube-row">'; + for (var r = 0; r < 6; r++) { + h += '<div class="cp-grid cp-cube">'; + for (var g = 0; g < 6; g++) { + for (var b = 0; b < 6; b++) { + var idx = 16 + 36*r + 6*g + b; + var css = xtermToCss(idx); + h += '<div class="cp-swatch" data-idx="'+idx+'" style="background:'+css+'" title="'+xtermIdxToHex(idx)+' ('+idx+')"></div>'; + } + } + h += '</div>'; + } + h += '</div>'; + + // Grayscale 232-255 (2 rows of 12) + h += '<div class="cp-section-label">Grayscale</div>'; + h += '<div class="cp-grid cp-gray">'; + for (var i = 232; i < 256; i++) { + var css = xtermToCss(i); + h += '<div class="cp-swatch" data-idx="'+i+'" style="background:'+css+'" title="'+xtermIdxToHex(i)+' ('+i+')"></div>'; + } + h += '</div>'; + return h; } |
