aboutsummaryrefslogtreecommitdiff
path: root/internal
diff options
context:
space:
mode:
Diffstat (limited to 'internal')
-rw-r--r--internal/admin/api_colors.go53
-rw-r--r--internal/admin/static/admin.css11
-rw-r--r--internal/admin/static/coloreditor.js45
-rw-r--r--internal/admin/static/colorpicker.js35
4 files changed, 95 insertions, 49 deletions
diff --git a/internal/admin/api_colors.go b/internal/admin/api_colors.go
index 78e5f98..0493b6c 100644
--- a/internal/admin/api_colors.go
+++ b/internal/admin/api_colors.go
@@ -144,17 +144,15 @@ func buildPreview() []colorSection {
sections = append(sections, colorSection{
Title: "Room Look",
Lines: []colorLine{
- ln(seg("[", "dim"), seg("*", "map_at"), seg("] ", "dim"),
- seg("Test Room", "room_name"),
- seg(" (", ""), seg("intro", "room_desc"), seg(", ", ""),
- seg("#2001", "room_number"), seg(")", "")),
+ ln(seg("Test Room", "room_name"),
+ seg(" (intro, #2001)", "room_number")),
txt(""),
ln(seg("It's a test room", "room_desc")),
txt(""),
ln(seg("A tree is here.", "room_desc")),
txt(""),
- ln(seg("A sentry ", "protected_mob"), seg("(level 4) watches the gate.", "")),
- ln(seg("A man ", "mob"), seg("(level 5) scribbles something in a small notebook.", "")),
+ ln(seg("A sentry ", "protected_mob"), seg("(level 4)", ""), seg(" watches the gate.", "")),
+ ln(seg("A man ", "mob"), seg("(level 5)", ""), seg(" scribbles something in a small notebook.", "")),
txt(""),
ln(seg("Icarus", "player_name"), seg(" is here.", "")),
txt(""),
@@ -167,20 +165,13 @@ func buildPreview() []colorSection {
txt(""),
txt("Exits:"),
ln(seg(" ", ""), seg("south", "exit_direction"), seg(" - ", ""), seg("Test Room", "exit_name")),
- ln(seg(" ", ""), seg("east", "exit_direction"), seg(" - ", ""), seg("Room ", "exit_name"), seg("#1005", "room_number")),
+ ln(seg(" ", ""), seg("east", "exit_direction"), seg(" - ", ""), seg("Processing Station", "exit_name")),
ln(seg(" ", ""), seg("west", "exit_direction"), seg(" - ", ""), seg("Inside Transport Shuttle", "exit_name")),
txt(""),
ln(seg(">", "dim")),
- },
- })
-
- // --- Movement ---------------------------------------------------------
- sections = append(sections, colorSection{
- Title: "Movement",
- Lines: []colorLine{
- ln(seg("You walk ", ""), seg("south", "direction"), seg(" to ", ""),
- seg("Test Room", "room_name"), seg(" (", ""), seg("#2001", "room_number"), seg(")", "")),
- ln(seg("WARNING: that area is exposed to ", ""), seg("radiation", "warning"), seg(".", "")),
+ txt(""),
+ ln(seg("> s", "dim")),
+ ln(seg("You walk ", ""), seg("south", "direction"), seg(".", "")),
},
})
@@ -193,23 +184,25 @@ func buildPreview() []colorSection {
txt(""),
ln(seg("You attack ", ""), seg("the man", "mob"), seg("! Style: accurate (+3 atk)", "")),
ln(seg("You hit ", ""), seg("the man", "mob"), seg(" for ", ""),
- seg("\u25B8 6 \u25C2 damage. [\u2588\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591] [ 1/7]", "damage_dealt"),
+ seg("\U0001FB38 6 \U0001FB34 damage. [█░░░░░░░░░] [ 1/7]", "damage_dealt"),
seg(" (+18xp acc, +6xp hp)", "xp")),
- ln(seg("The man", "mob"), seg(" misses you.", "miss")),
+ ln(seg("The man misses you.", "miss")),
ln(seg("You hit ", ""), seg("the man", "mob"), seg(" for ", ""),
- seg("\u25B8 6 \u25C2 damage. [\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591] [ 0/7]", "damage_dealt"),
+ seg("\U0001FB38 6 \U0001FB34 damage. [░░░░░░░░░░] [ 0/7]", "damage_dealt"),
seg(" (+18xp acc, +6xp hp)", "xp")),
ln(seg("You have defeated ", ""), seg("the man", "mob"), seg("!", "victory")),
ln(seg("*** You are now level 12 melee! ***", "level_up")),
txt(""),
ln(seg("A scout", "mob"), seg(" hits you for ", ""),
- seg("\u25B8 5 \u25C2 damage. [\u2588\u2588\u2588\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591] [22/40]", "damage_taken")),
+ seg("\U0001FB38 5 \U0001FB34 damage. [██████░░░░] [22/40]", "damage_taken")),
ln(seg("A scout's attack is extra effective! Equip ", ""),
seg("plated vest", "warning"), seg(" for protection.", "")),
ln(seg("You attack ", ""), seg("a scout", "mob"), seg(" with ", ""), seg("laser cutter", "science_mod"), seg("!", "")),
- ln(seg("You miss ", ""), seg("a scout", "mob"), seg(".", "miss")),
+ ln(seg("You miss a scout.", "miss")),
ln(seg("Oh dear, you are dead!", "death")),
- ln(seg("Error: command not recognized.", "error")),
+ txt(""),
+ ln(seg("> help!", "dim")),
+ ln(seg("Unknown command.", "error")),
txt(""),
ln(seg("(", ""), seg("damage", "damage"), seg(" is a config-only alt key, not emitted by the engine)", "")),
},
@@ -284,13 +277,13 @@ func buildPreview() []colorSection {
sections = append(sections, colorSection{
Title: "Mini Map",
Lines: []colorLine{
- ln(seg("\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557", "dim")),
- ln(seg("\u2551", "dim"), seg("\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591", "map_blocked"), seg("\u2551", "dim")),
- ln(seg("\u2551", "dim"), seg("\u2591\u2591", "map_blocked"), seg("@", "map_at"), seg("\u2591\u2591", "map_blocked"), seg("\u2502", "map_course"), seg("\u2591\u2591\u2591\u2591", "map_blocked"), seg("\u2551", "dim")),
- ln(seg("\u2551", "dim"), seg("\u2591\u2591\u2591\u2591\u2591", "map_blocked"), seg("\u2502", "map_course"), seg("\u2591\u2591\u2591\u2591", "map_blocked"), seg("\u2551", "dim")),
- ln(seg("\u2551", "dim"), seg("\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591\u2591", "map_blocked"), seg("\u2551", "dim")),
- ln(seg("\u255a\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255d", "dim")),
- ln(seg(" ", ""), seg("Room #2002", "room_number")),
+ ln(seg("╔═════╗", "dim")),
+ ln(seg("║", "dim"), seg(" ", ""), seg("░", "map_blocked"), seg(" ", ""), seg("║", "dim")),
+ ln(seg("║", "dim"), seg(" ", ""), seg("║", "dim")),
+ ln(seg("║", "dim"), seg("■", ""), seg("-", ""), seg("@", "map_at"), seg("-", ""), seg("■", ""), seg("║", "dim")),
+ ln(seg("║", "dim"), seg(" ", ""), seg("│", "map_course"), seg(" ", ""), seg("║", "dim")),
+ ln(seg("║", "dim"), seg(" ", ""), seg("■", ""), seg(" ", ""), seg("║", "dim")),
+ ln(seg("╚═════╝", "dim")),
},
})
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;
}