aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-06-13 16:57:35 -0500
committerCraig Jennings <c@cjennings.net>2026-06-13 16:57:35 -0500
commit7726880836bca46c84795728fc61ef69a68835b9 (patch)
tree768346ae84f89a2a70a19ad0ae8d79b6737334c1
parentf2285ee52f9712ef431fa010ffeb1590dcc6983c (diff)
downloaddotemacs-7726880836bca46c84795728fc61ef69a68835b9.tar.gz
dotemacs-7726880836bca46c84795728fc61ef69a68835b9.zip
Fix theme studio ground column order
-rw-r--r--scripts/theme-studio/app.js23
-rw-r--r--scripts/theme-studio/theme-studio.html23
2 files changed, 34 insertions, 12 deletions
diff --git a/scripts/theme-studio/app.js b/scripts/theme-studio/app.js
index 18118f7c..50271f1c 100644
--- a/scripts/theme-studio/app.js
+++ b/scripts/theme-studio/app.js
@@ -161,14 +161,19 @@ function normalizePaletteEntry(entry){
return [hex,name,(entry&&entry[2])||columnIdOf(entry)];
}
function normalizePalette(){PALETTE=PALETTE.map(normalizePaletteEntry);}
-// The ground column is explicit: bg pins the dark endpoint, fg pins the light
+// The ground column is explicit: bg pins the top endpoint, fg pins the bottom
// endpoint, and generated ground-N steps live between them.
function groundColumnMembers(){
- const members=[];
- for(const entry of PALETTE)if(groundRoleOfEntry(entry,{bg:MAP['bg'],fg:MAP['p']}))members.push({hex:entry[0],name:entry[1]});
- if(!PALETTE.some(entry=>groundRoleOfEntry(entry,{bg:MAP['bg'],fg:MAP['p']})==='bg'))members.push({hex:MAP['bg'],name:'bg'});
- if(!PALETTE.some(entry=>groundRoleOfEntry(entry,{bg:MAP['bg'],fg:MAP['p']})==='fg'))members.push({hex:MAP['p'],name:'fg'});
- return members.sort((a,b)=>oklab2oklch(srgb2oklab(a.hex)).L-oklab2oklch(srgb2oklab(b.hex)).L);
+ const ground={bg:MAP['bg'],fg:MAP['p']};
+ const byRole={bg:null,fg:null,steps:[]};
+ for(const entry of PALETTE){
+ const role=groundRoleOfEntry(entry,ground);
+ if(role==='bg'||role==='fg')byRole[role]={hex:entry[0],name:entry[1]};
+ else if(role==='step')byRole.steps.push({hex:entry[0],name:entry[1]});
+ }
+ const stepIndex=m=>{const x=(m.name||'').match(/^ground-(\d+)$/i);return x?parseInt(x[1],10):Infinity;};
+ byRole.steps.sort((a,b)=>stepIndex(a)-stepIndex(b));
+ return [byRole.bg||{hex:MAP['bg'],name:'bg'},...byRole.steps,byRole.fg||{hex:MAP['p'],name:'fg'}];
}
function groundSpanCount(){return PALETTE.filter(entry=>groundRoleOfEntry(entry,{bg:MAP['bg'],fg:MAP['p']})==='step').length;}
function groundSpanControl(){
@@ -1332,6 +1337,12 @@ if(location.hash==='#counttest'){let ok=true;const notes=[];const A=(c,n)=>{if(!
A(MAP['bg']==='#204060'&&MAP['p']==='#f0fef0','spanning ground keeps bg/fg assignments on endpoints');
A(PALETTE.some(p=>p[1]==='ground-1')&&PALETTE.some(p=>p[1]==='ground-2'),'spanning ground adds interior ground-N entries');
A(document.querySelector('#pals .fstrip[data-column="ground"] .fhead + .fcount + .pchip'),'ground span control renders before tiles');
+ MAP['bg']='#ffffff';MAP['p']='#000000';
+ PALETTE=[['#ffffff','bg'],['#bbbbbb','ground-1','ground'],['#777777','ground-2','ground'],['#000000','fg']];
+ renderPalette();
+ const groundNames=[...document.querySelectorAll('#pals .fstrip[data-column="ground"] .pchip .nm')].map(e=>e.value);
+ A(groundNames.join('|')==='bg|ground-1|ground-2|fg','ground column order is bg, ground steps, fg even when bg is lighter: '+groundNames.join('|'));
+ MAP['bg']='#204060';MAP['p']='#f0fef0';
setGroundSpan(1);
A(!PALETTE.some(p=>p[1]==='ground-2'),'lowering ground span removes dropped interior steps');
PALETTE=[['#204060','bg'],['#f0fef0','fg']];
diff --git a/scripts/theme-studio/theme-studio.html b/scripts/theme-studio/theme-studio.html
index 44156648..9b1b79da 100644
--- a/scripts/theme-studio/theme-studio.html
+++ b/scripts/theme-studio/theme-studio.html
@@ -817,14 +817,19 @@ function normalizePaletteEntry(entry){
return [hex,name,(entry&&entry[2])||columnIdOf(entry)];
}
function normalizePalette(){PALETTE=PALETTE.map(normalizePaletteEntry);}
-// The ground column is explicit: bg pins the dark endpoint, fg pins the light
+// The ground column is explicit: bg pins the top endpoint, fg pins the bottom
// endpoint, and generated ground-N steps live between them.
function groundColumnMembers(){
- const members=[];
- for(const entry of PALETTE)if(groundRoleOfEntry(entry,{bg:MAP['bg'],fg:MAP['p']}))members.push({hex:entry[0],name:entry[1]});
- if(!PALETTE.some(entry=>groundRoleOfEntry(entry,{bg:MAP['bg'],fg:MAP['p']})==='bg'))members.push({hex:MAP['bg'],name:'bg'});
- if(!PALETTE.some(entry=>groundRoleOfEntry(entry,{bg:MAP['bg'],fg:MAP['p']})==='fg'))members.push({hex:MAP['p'],name:'fg'});
- return members.sort((a,b)=>oklab2oklch(srgb2oklab(a.hex)).L-oklab2oklch(srgb2oklab(b.hex)).L);
+ const ground={bg:MAP['bg'],fg:MAP['p']};
+ const byRole={bg:null,fg:null,steps:[]};
+ for(const entry of PALETTE){
+ const role=groundRoleOfEntry(entry,ground);
+ if(role==='bg'||role==='fg')byRole[role]={hex:entry[0],name:entry[1]};
+ else if(role==='step')byRole.steps.push({hex:entry[0],name:entry[1]});
+ }
+ const stepIndex=m=>{const x=(m.name||'').match(/^ground-(\d+)$/i);return x?parseInt(x[1],10):Infinity;};
+ byRole.steps.sort((a,b)=>stepIndex(a)-stepIndex(b));
+ return [byRole.bg||{hex:MAP['bg'],name:'bg'},...byRole.steps,byRole.fg||{hex:MAP['p'],name:'fg'}];
}
function groundSpanCount(){return PALETTE.filter(entry=>groundRoleOfEntry(entry,{bg:MAP['bg'],fg:MAP['p']})==='step').length;}
function groundSpanControl(){
@@ -1988,6 +1993,12 @@ if(location.hash==='#counttest'){let ok=true;const notes=[];const A=(c,n)=>{if(!
A(MAP['bg']==='#204060'&&MAP['p']==='#f0fef0','spanning ground keeps bg/fg assignments on endpoints');
A(PALETTE.some(p=>p[1]==='ground-1')&&PALETTE.some(p=>p[1]==='ground-2'),'spanning ground adds interior ground-N entries');
A(document.querySelector('#pals .fstrip[data-column="ground"] .fhead + .fcount + .pchip'),'ground span control renders before tiles');
+ MAP['bg']='#ffffff';MAP['p']='#000000';
+ PALETTE=[['#ffffff','bg'],['#bbbbbb','ground-1','ground'],['#777777','ground-2','ground'],['#000000','fg']];
+ renderPalette();
+ const groundNames=[...document.querySelectorAll('#pals .fstrip[data-column="ground"] .pchip .nm')].map(e=>e.value);
+ A(groundNames.join('|')==='bg|ground-1|ground-2|fg','ground column order is bg, ground steps, fg even when bg is lighter: '+groundNames.join('|'));
+ MAP['bg']='#204060';MAP['p']='#f0fef0';
setGroundSpan(1);
A(!PALETTE.some(p=>p[1]==='ground-2'),'lowering ground span removes dropped interior steps');
PALETTE=[['#204060','bg'],['#f0fef0','fg']];