aboutsummaryrefslogtreecommitdiff
path: root/internal/admin/static
diff options
context:
space:
mode:
authorhistoria <[not public]>2026-07-15 06:19:05 -0400
committerhistoria <[not public]>2026-07-15 06:19:05 -0400
commite09e7badbc722f580a9d7674c46d6ff3cc320b26 (patch)
treea6beb1ed8a2ed3e2ae2334a619a1e0b40e5030d6 /internal/admin/static
parent84dd8c7557d8b9d92cd8d339afc28a0fd9a3a896 (diff)
downloadthehouseoficarus-e09e7badbc722f580a9d7674c46d6ff3cc320b26.tar.gz
feat(admin): color picker shows color cube correctly
Diffstat (limited to 'internal/admin/static')
-rw-r--r--internal/admin/static/admin.css11
-rw-r--r--internal/admin/static/coloreditor.js45
-rw-r--r--internal/admin/static/colorpicker.js35
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">&times;</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;
}