aboutsummaryrefslogtreecommitdiff
path: root/scripts/theme-studio/theme-studio.html
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/theme-studio/theme-studio.html')
-rw-r--r--scripts/theme-studio/theme-studio.html18
1 files changed, 18 insertions, 0 deletions
diff --git a/scripts/theme-studio/theme-studio.html b/scripts/theme-studio/theme-studio.html
index 1716db9b..27df2a83 100644
--- a/scripts/theme-studio/theme-studio.html
+++ b/scripts/theme-studio/theme-studio.html
@@ -613,6 +613,24 @@ function stepRepointPlan(oldRanked,newMembers){
}
return {map,removed};
}
+
+// Order a family's members dark to light by OKLCH lightness.
+function sortFamilyMembers(fam){return Object.assign({},fam,{members:[...fam.members].sort((a,b)=>oklchOf(a.hex).L-oklchOf(b.hex).L)});}
+// Order families for display: neutrals first (by base lightness), then chromatic
+// by base hue, ties broken by base lightness then base hex. Each family's members
+// are lightness-sorted. Display-only — the stored palette order is untouched.
+function sortFamilies(families){
+ const keyed=families.map(f=>{const c=oklchOf(f.base);return {f,neutral:!!f.neutral,H:c.H,L:c.L,base:f.base};});
+ keyed.sort((a,b)=>{
+ if(a.neutral!==b.neutral)return a.neutral?-1:1;
+ if(a.neutral&&b.neutral)return a.L-b.L;
+ const ah=Math.round(a.H),bh=Math.round(b.H); // a hue hair shouldn't outrank lightness
+ if(ah!==bh)return ah-bh;
+ if(a.L!==b.L)return a.L-b.L;
+ return a.base.toLowerCase()<b.base.toLowerCase()?-1:a.base.toLowerCase()>b.base.toLowerCase()?1:0;
+ });
+ return keyed.map(k=>sortFamilyMembers(k.f));
+}
// Pure color/UI-boundary helpers (normHex, ratingColor, textOn), inlined from
// app-util.js. textOn uses rl from the colormath core above.
// Pure color/UI-boundary helpers: hex-input parsing, the contrast-rating status