aboutsummaryrefslogtreecommitdiff
path: root/scripts/theme-studio/app-core.js
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-06-13 17:17:31 -0500
committerCraig Jennings <c@cjennings.net>2026-06-13 17:17:31 -0500
commitd93560446f954a44890b8472f90d57c3080993df (patch)
treeda5f94a93fb296709f1c1272a2c118ffee47dac5 /scripts/theme-studio/app-core.js
parentc18d914c138d04157afe64a64b7cd47aaa3171b0 (diff)
downloaddotemacs-d93560446f954a44890b8472f90d57c3080993df.tar.gz
dotemacs-d93560446f954a44890b8472f90d57c3080993df.zip
Refactor theme studio palette tests
Diffstat (limited to 'scripts/theme-studio/app-core.js')
-rw-r--r--scripts/theme-studio/app-core.js42
1 files changed, 41 insertions, 1 deletions
diff --git a/scripts/theme-studio/app-core.js b/scripts/theme-studio/app-core.js
index 1a4a121f..5e889bed 100644
--- a/scripts/theme-studio/app-core.js
+++ b/scripts/theme-studio/app-core.js
@@ -160,6 +160,46 @@ function nameOfGroundRole(palette,ground,role){
return found?found[1]:null;
}
+function normalizePaletteEntryCore(entry){
+ const hex=entry&&entry[0],name=(entry&&entry[1])||'color';
+ return [hex,name,(entry&&entry[2])||columnIdOf(entry)];
+}
+
+function groundColumnMembersFromPalette(palette,ground){
+ 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:ground&&ground.bg,name:'bg'},...byRole.steps,byRole.fg||{hex:ground&&ground.fg,name:'fg'}].filter(m=>m.hex);
+}
+
+function clearPalettePlan(palette,ground){
+ const normalized=palette.map(normalizePaletteEntryCore),removed=[],keep=[];
+ normalized.filter(entry=>!groundRoleOfEntry(entry,ground)).forEach(([hex,name])=>{if(name)removed.push({hex,name});});
+ const addEndpoint=(role,hex,name)=>{
+ const found=normalized.find(entry=>groundRoleOfEntry(entry,ground)===role);
+ if(found)keep.push(found);else if(hex)keep.push([hex,name,'ground']);
+ };
+ addEndpoint('bg',ground&&ground.bg,'bg');
+ addEndpoint('fg',ground&&ground.fg,'fg');
+ return {palette:keep,removed};
+}
+
+function areAllLocked(keys,locked){
+ const has=k=>locked instanceof Set?locked.has(k):Array.isArray(locked)&&locked.includes(k);
+ return !!(keys&&keys.length)&&keys.every(has);
+}
+function lockToggleLabel(keys,locked){return areAllLocked(keys,locked)?'unlock all':'lock all';}
+function toggleLockSet(keys,locked){
+ const next=new Set(locked||[]),all=areAllLocked(keys,next);
+ (keys||[]).forEach(k=>all?next.delete(k):next.add(k));
+ return next;
+}
+
// Group a flat palette into the ground strip plus structural columns. ground is
// {bg,fg}; those endpoint hexes form the pinned ground column even when absent
// from the palette, and ground-N entries are reserved for that column. Everything
@@ -241,4 +281,4 @@ function paletteOptionList(cur,palette,ground){
return out;
}
-export { nameToHex, normalizePkgFace, buildPkgmap, packagesForExport, mergePackagesInto, effResolve, optList, paletteOptionList, slugify, ramp, fgSetFor, floor, lMax, COVERED_FACES, columnsFromPalette, regenColumn, rankByLightness, stepRepointPlan, sortColumns, sortColumnMembers, groundRoleOfEntry };
+export { nameToHex, normalizePkgFace, buildPkgmap, packagesForExport, mergePackagesInto, effResolve, optList, paletteOptionList, slugify, ramp, fgSetFor, floor, lMax, COVERED_FACES, columnsFromPalette, regenColumn, rankByLightness, stepRepointPlan, sortColumns, sortColumnMembers, groundRoleOfEntry, groundColumnMembersFromPalette, clearPalettePlan, areAllLocked, lockToggleLabel, toggleLockSet };