@taprootio/espalier 2.15.4 → 2.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- import{parseOklch as y,serializeOklch as p,gamutMapToSRGB as S,deriveSemantic as v,deriveSemanticWithContrast as B}from"../../shared/color-engine.js";import{generateScaleProperties as x}from"../../shared/scale-engine.js";import{SEMANTIC_COLOR_NAMES as l,LIGHTNESS_KEYS as C,semanticToCSS as b}from"../../shared/theme.js";import{lightnessKeyToCSS as I}from"./lightness-key-to-css.js";import{computeVariants as O}from"./compute-variants.js";function M(o){return{rootFontSize:o.rootFontSize,typeRatio:o.typeRatio,spaceRatio:o.spaceRatio,borderRadius:o.borderRadius,viewportMin:o.viewportMin,viewportMax:o.viewportMax}}function W(o,k){const d=y(o.seedColor);if(!d)return{};const n={};n["--esp-scheme"]=k,n["--esp-seed-color"]=o.seedColor;const c=O(d,o);for(const[a,t]of Object.entries(c))n[`--esp-color-${a}`]=p(S(t));for(const a of C)n[I(a)]=`${Math.round(o.lightness[a]*100)}%`;const u={text:{bg:"background",targetLc:75},dangerText:{bg:"background",targetLc:75},headings:{bg:"background",targetLc:60},headingsHover:{bg:"background",targetLc:60},link:{bg:"background",targetLc:75},linkHover:{bg:"background",targetLc:75},actionText:{bg:"actionBackground",targetLc:75},inputCaret:{bg:"layer2",targetLc:60},inputSelection:{bg:"inputSelectionBg",targetLc:60}},s={};for(const a of l){if(u[a])continue;const t=o.semanticMappings[a],i=o.chroma[a],r=c[t.source],e=o.lightness[t.lightness],g=v(r,e,i.min,i.max);s[a]=g,n[b(a)]=p(g)}for(const a of l){const t=u[a];if(!t)continue;const i=o.semanticMappings[a],r=o.chroma[a],e=c[i.source],g=o.lightness[i.lightness],m=s[t.bg],f=B(e,g,r.min,r.max,m,t.targetLc);s[a]=f,n[b(a)]=p(f)}return Object.assign(n,x(M(o))),o.fontBody&&(n["--esp-font-body"]=o.fontBody),o.fontHeadings&&(n["--esp-font-headings"]=o.fontHeadings),o.fontBrand&&(n["--esp-font-brand"]=o.fontBrand),o.fontMonospace&&(n["--esp-font-monospace"]=o.fontMonospace),n["--esp-font-weight-body"]=o.fontWeightBody,n["--esp-font-weight-headings"]=o.fontWeightHeadings,n["--esp-font-weight-brand"]=o.fontWeightBrand,n["--esp-font-weight-monospace"]=o.fontWeightMonospace,o.pageBackgroundImage&&(n["--esp-page-background-image"]=o.pageBackgroundImage),o.pageBackgroundImageOpacity!==void 0&&(n["--esp-page-background-image-opacity"]=o.pageBackgroundImageOpacity.toString()),o.boxBackgroundImage&&(n["--esp-box-background-image"]=o.boxBackgroundImage),o.boxBackgroundImageOpacity!==void 0&&(n["--esp-box-background-image-opacity"]=o.boxBackgroundImageOpacity.toString()),o.vellumOpacity!==void 0&&(n["--esp-vellum-opacity"]=o.vellumOpacity.toString()),o.vellumBackgroundImage&&(n["--esp-vellum-background-image"]=o.vellumBackgroundImage),o.vellumBackgroundImageOpacity!==void 0&&(n["--esp-vellum-background-image-opacity"]=o.vellumBackgroundImageOpacity.toString()),n}export{W as computeThemeProperties};
1
+ import{parseCssColor as y,serializeOklch as p,gamutMapToSRGB as B,deriveSemantic as C,deriveSemanticWithContrast as x}from"../../shared/color-engine.js";import{generateScaleProperties as I}from"../../shared/scale-engine.js";import{SEMANTIC_COLOR_NAMES as k,LIGHTNESS_KEYS as M,semanticToCSS as m}from"../../shared/theme.js";import{lightnessKeyToCSS as O}from"./lightness-key-to-css.js";import{computeVariants as L,resolveMappingSource as w}from"./compute-variants.js";function R(o){return{rootFontSize:o.rootFontSize,typeRatio:o.typeRatio,spaceRatio:o.spaceRatio,borderRadius:o.borderRadius,viewportMin:o.viewportMin,viewportMax:o.viewportMax}}function N(o,S){const d=y(o.seedColor);if(!d)return{};const n={};n["--esp-scheme"]=S,n["--esp-seed-color"]=o.seedColor;const e=L(d,o);for(const[a,t]of Object.entries(e))n[`--esp-color-${a}`]=p(B(t));for(const a of M)n[O(a)]=`${Math.round(o.lightness[a]*100)}%`;const u={text:{bg:"background",targetLc:75},dangerText:{bg:"background",targetLc:75},headings:{bg:"background",targetLc:60},headingsHover:{bg:"background",targetLc:60},link:{bg:"background",targetLc:75},linkHover:{bg:"background",targetLc:75},actionText:{bg:"actionBackground",targetLc:75},inputCaret:{bg:"layer2",targetLc:60},inputSelection:{bg:"inputSelectionBg",targetLc:60}},f=new Set,l=a=>{const t=w(a,e,o.anchors);return t||(f.has(a)||(f.add(a),console.warn(`Espalier theme: color source "${a}" cannot be resolved \u2014 falling back to the seed. Run validateTheme for the declared anchors.`)),e.primary)},g={};for(const a of k){if(u[a])continue;const t=o.semanticMappings[a],r=o.chroma[a],i=l(t.source),s=o.lightness[t.lightness],c=C(i,s,r.min,r.max);g[a]=c,n[m(a)]=p(c)}for(const a of k){const t=u[a];if(!t)continue;const r=o.semanticMappings[a],i=o.chroma[a],s=l(r.source),c=o.lightness[r.lightness],v=g[t.bg],b=x(s,c,i.min,i.max,v,t.targetLc);g[a]=b,n[m(a)]=p(b)}return Object.assign(n,I(R(o))),o.fontBody&&(n["--esp-font-body"]=o.fontBody),o.fontHeadings&&(n["--esp-font-headings"]=o.fontHeadings),o.fontBrand&&(n["--esp-font-brand"]=o.fontBrand),o.fontMonospace&&(n["--esp-font-monospace"]=o.fontMonospace),n["--esp-font-weight-body"]=o.fontWeightBody,n["--esp-font-weight-headings"]=o.fontWeightHeadings,n["--esp-font-weight-brand"]=o.fontWeightBrand,n["--esp-font-weight-monospace"]=o.fontWeightMonospace,o.pageBackgroundImage&&(n["--esp-page-background-image"]=o.pageBackgroundImage),o.pageBackgroundImageOpacity!==void 0&&(n["--esp-page-background-image-opacity"]=o.pageBackgroundImageOpacity.toString()),o.boxBackgroundImage&&(n["--esp-box-background-image"]=o.boxBackgroundImage),o.boxBackgroundImageOpacity!==void 0&&(n["--esp-box-background-image-opacity"]=o.boxBackgroundImageOpacity.toString()),o.vellumOpacity!==void 0&&(n["--esp-vellum-opacity"]=o.vellumOpacity.toString()),o.vellumBackgroundImage&&(n["--esp-vellum-background-image"]=o.vellumBackgroundImage),o.vellumBackgroundImageOpacity!==void 0&&(n["--esp-vellum-background-image-opacity"]=o.vellumBackgroundImageOpacity.toString()),n}export{N as computeThemeProperties};
@@ -1 +1 @@
1
- import{rotateHue as l}from"../../shared/color-engine.js";const h=.6,p=.85;function s(t,i){const{angles:c,semanticHues:n,variantChroma:o}=i,a=m=>o[m]??t.c,r=Math.min(p,Math.max(h,t.l));return{primary:t,"analogous-left":{l:t.l,c:a("analogous-left"),h:l(t.h,-c.analogous)},"analogous-right":{l:t.l,c:a("analogous-right"),h:l(t.h,c.analogous)},complementary:{l:t.l,c:a("complementary"),h:l(t.h,c.complementary)},"split-complementary-left":{l:t.l,c:a("split-complementary-left"),h:l(t.h,c.complementary-c.splitComplementary)},"split-complementary-right":{l:t.l,c:a("split-complementary-right"),h:l(t.h,c.complementary+c.splitComplementary)},"triadic-left":{l:t.l,c:a("triadic-left"),h:l(t.h,c.triadic)},"triadic-right":{l:t.l,c:a("triadic-right"),h:l(t.h,-c.triadic)},danger:{l:r,c:a("danger"),h:l(n.danger,0)},success:{l:r,c:a("success"),h:l(n.success,0)},warning:{l:r,c:a("warning"),h:l(n.warning,0)}}}export{s as computeVariants};
1
+ import{parseCssColor as h,rotateHue as n}from"../../shared/color-engine.js";import{parseAnchorSource as e,resolveAnchorColor as p}from"../../shared/theme.js";const s=.6,u=.85;function y(t,c){const{angles:r,semanticHues:a,variantChroma:o}=c,l=m=>o[m]??t.c,i=Math.min(u,Math.max(s,t.l));return{primary:t,"analogous-left":{l:t.l,c:l("analogous-left"),h:n(t.h,-r.analogous)},"analogous-right":{l:t.l,c:l("analogous-right"),h:n(t.h,r.analogous)},complementary:{l:t.l,c:l("complementary"),h:n(t.h,r.complementary)},"split-complementary-left":{l:t.l,c:l("split-complementary-left"),h:n(t.h,r.complementary-r.splitComplementary)},"split-complementary-right":{l:t.l,c:l("split-complementary-right"),h:n(t.h,r.complementary+r.splitComplementary)},"triadic-left":{l:t.l,c:l("triadic-left"),h:n(t.h,r.triadic)},"triadic-right":{l:t.l,c:l("triadic-right"),h:n(t.h,-r.triadic)},danger:{l:i,c:l("danger"),h:n(a.danger,0)},success:{l:i,c:l("success"),h:n(a.success,0)},warning:{l:i,c:l("warning"),h:n(a.warning,0)}}}function S(t,c,r){const a=e(t);if(!a)return c[t]??null;const o=p(r,a);return o===null?null:h(o)}export{y as computeVariants,S as resolveMappingSource};
@@ -1 +1 @@
1
- const S=Math.PI/180,s=1e-4,w=50;function P(t){const o=t.h*S;return{L:t.l,a:t.c*Math.cos(o),b:t.c*Math.sin(o)}}function k(t){const o=t.L+.3963377774*t.a+.2158037573*t.b,e=t.L-.1055613458*t.a-.0638541728*t.b,n=t.L-.0894841775*t.a-1.291485548*t.b,r=o*o*o,c=e*e*e,a=n*n*n;return{r:4.0767416621*r-3.3077115913*c+.2309699292*a,g:-1.2684380046*r+2.6097574011*c-.3413193965*a,b:-.0041960863*r-.7034186147*c+1.707614701*a}}function p(t){return t<=.0031308?12.92*t:1.055*Math.pow(t,1/2.4)-.055}function N(t){return{r:p(t.r),g:p(t.g),b:p(t.b)}}function O(t){return t.r>=-s&&t.r<=1+s&&t.g>=-s&&t.g<=1+s&&t.b>=-s&&t.b<=1+s}function M(t){return Math.max(0,Math.min(1,t))}function X(t){const e=t.trim().match(/^oklch\(\s*([\d.]+)(%?)\s+([\d.]+)\s+([\d.]+)\s*\)$/i);if(!e)return null;let n=parseFloat(e[1]);e[2]==="%"&&(n/=100);const r=parseFloat(e[3]),c=parseFloat(e[4]);return isNaN(n)||isNaN(r)||isNaN(c)?null:{l:n,c:r,h:(c%360+360)%360}}function $(t){const o=T(t.l,6),e=T(t.c,6),n=T((t.h%360+360)%360,4);return`oklch(${o} ${e} ${n})`}function m(t){return N(k(P(t)))}function _(t){return O(m(t))}function h(t){if(t.c<=s||_(t))return{...t};let o=0,e=t.c,n={...t};for(let r=0;r<w;r++){const c=(o+e)/2;if(n={l:t.l,c,h:t.h},_(n)?o=c:e=c,e-o<s)break}return{l:t.l,c:o,h:t.h}}function E(t,o,e){const n={l:t.l,c:Math.max(o,Math.min(e,t.c)),h:t.h};return h(n)}const f=.022,G=.012,x=.022,C=.57,L=.56,R=1.14,A=.001,l=.027;function d(t){const o=Math.pow(M(t.r),2.4),e=Math.pow(M(t.g),2.4),n=Math.pow(M(t.b),2.4);return .2126729*o+.7151522*e+.072175*n}function B(t,o){const e=m(h(t)),n=m(h(o));let r=d(e),c=d(n);if(r=r>f?r:r+Math.pow(f-r,1.414),c=c>f?c:c+Math.pow(f-c,1.414),Math.abs(c-r)<A)return 0;let a;if(c>r){const i=Math.pow(c,L),u=Math.pow(r,C);if(a=(i-u)*R,a<A)return 0;a=a<l?a-a*x*l:a-x}else{const i=Math.pow(c,L),u=Math.pow(r,C);if(a=(i-u)*R,a>-A)return 0;a=a>-l?a-a*G*l:a+G}return a*100}function F(t,o,e=60){let n=h({...t}),r=Math.abs(B(n,o));if(r>=e)return n;const c=o.l>.5,a=.01,i=c?0:1;for(let u=0;u<100;u++){if(c?n.l=Math.max(i,n.l-a):n.l=Math.min(i,n.l+a),n=h(n),r=Math.abs(B(n,o)),r>=e)return n;if(n.l<=0||n.l>=1)break}return n}function b(t,o){return((t+o)%360+360)%360}function I(t,o,e,n){return E({l:o,c:t.c,h:t.h},e,n)}function W(t,o,e,n,r,c=60){const a=I(t,o,e,n);return F(a,r,c)}function T(t,o){const e=Math.pow(10,o);return Math.round(t*e)/e}export{B as apcaContrast,E as clampChromaAndGamutMap,I as deriveSemantic,W as deriveSemanticWithContrast,F as ensureContrast,h as gamutMapToSRGB,_ as isInSRGBGamut,m as oklchToSRGB,X as parseOklch,b as rotateHue,$ as serializeOklch};
1
+ const S=Math.PI/180,h=1e-4,$=50,m="[+-]?(?:\\d+|\\d*\\.\\d+)(?:[eE][+-]?\\d+)?",i="[\\t\\n\\f\\r ]",X=new RegExp(i+"*,"+i+"*"),y=new RegExp(i+"+");function G(t){return t.replace(/\/\*[\s\S]*?(?:\*\/|$)/g," ").replace(/^[\t\n\f\r ]+|[\t\n\f\r ]+$/g,"")}const L={"":1,deg:1,grad:.9,rad:180/Math.PI,turn:360},H=.4,U=new RegExp("^oklch\\("+i+"*("+m+")(%?)"+i+"+("+m+")(%?)"+i+"+("+m+")(deg|grad|rad|turn)?"+i+"*\\)$","i");function V(t){const n=t.h*S;return{L:t.l,a:t.c*Math.cos(n),b:t.c*Math.sin(n)}}function W(t){const n=t.L+.3963377774*t.a+.2158037573*t.b,r=t.L-.1055613458*t.a-.0638541728*t.b,e=t.L-.0894841775*t.a-1.291485548*t.b,o=n*n*n,u=r*r*r,c=e*e*e;return{r:4.0767416621*o-3.3077115913*u+.2309699292*c,g:-1.2684380046*o+2.6097574011*u-.3413193965*c,b:-.0041960863*o-.7034186147*u+1.707614701*c}}function T(t){return t<=.0031308?12.92*t:1.055*Math.pow(t,1/2.4)-.055}function z(t){return{r:T(t.r),g:T(t.g),b:T(t.b)}}function Y(t){return t.r>=-h&&t.r<=1+h&&t.g>=-h&&t.g<=1+h&&t.b>=-h&&t.b<=1+h}function g(t){return Math.max(0,Math.min(1,t))}function q(t){const n=G(t).match(U);if(!n)return null;let r=parseFloat(n[1]);n[2]==="%"&&(r/=100);let e=parseFloat(n[3]);n[4]==="%"&&(e=e/100*H);const o=parseFloat(n[5])*L[(n[6]??"").toLowerCase()];return!isFinite(r)||!isFinite(e)||!isFinite(o)?null:{l:Math.max(0,Math.min(1,r)),c:Math.max(0,e),h:(o%360+360)%360}}function ct(t){const n=p(t.l,6),r=p(t.c,6),e=p((t.h%360+360)%360,4);return`oklch(${n} ${r} ${e})`}function _(t){return z(W(V(t)))}function x(t){return Y(_(t))}function M(t){if(t.c<=h||x(t))return{...t};let n=0,r=t.c,e={...t};for(let o=0;o<$;o++){const u=(n+r)/2;if(e={l:t.l,c:u,h:t.h},x(e)?n=u:r=u,r-n<h)break}return{l:t.l,c:n,h:t.h}}function K(t,n,r){const e={l:t.l,c:Math.max(n,Math.min(r,t.c)),h:t.h};return M(e)}const C=.022,w=.012,O=.022,b=.57,k=.56,P=1.14,A=.001,R=.027;function B(t){const n=Math.pow(g(t.r),2.4),r=Math.pow(g(t.g),2.4),e=Math.pow(g(t.b),2.4);return .2126729*n+.7151522*r+.072175*e}function I(t,n){const r=_(M(t)),e=_(M(n));let o=B(r),u=B(e);if(o=o>C?o:o+Math.pow(C-o,1.414),u=u>C?u:u+Math.pow(C-u,1.414),Math.abs(u-o)<A)return 0;let c;if(u>o){const s=Math.pow(u,k),a=Math.pow(o,b);if(c=(s-a)*P,c<A)return 0;c=c<R?c-c*O*R:c-O}else{const s=Math.pow(u,k),a=Math.pow(o,b);if(c=(s-a)*P,c>-A)return 0;c=c>-R?c-c*w*R:c+w}return c*100}function j(t,n,r=60){let e=M({...t}),o=Math.abs(I(e,n));if(o>=r)return e;const u=n.l>.5,c=.01,s=u?0:1;for(let a=0;a<100;a++){if(u?e.l=Math.max(s,e.l-c):e.l=Math.min(s,e.l+c),e=M(e),o=Math.abs(I(e,n)),o>=r)return e;if(e.l<=0||e.l>=1)break}return e}function st(t,n){return((t+n)%360+360)%360}function J(t,n,r,e){return K({l:n,c:t.c,h:t.h},r,e)}function at(t,n,r,e,o,u=60){const c=J(t,n,r,e);return j(c,o,u)}function E(t){return t<=.04045?t/12.92:Math.pow((t+.055)/1.055,2.4)}function Q(t){const n=E(t.r),r=E(t.g),e=E(t.b),o=Math.cbrt(.4122214708*n+.5363325363*r+.0514459929*e),u=Math.cbrt(.2119034982*n+.6806995451*r+.1073969566*e),c=Math.cbrt(.0883024619*n+.2817188376*r+.6299787005*e);return{L:.2104542553*o+.793617785*u-.0040720468*c,a:1.9779984951*o-2.428592205*u+.4505937099*c,b:.0259040371*o+.7827717662*u-.808675766*c}}function Z(t){const n=Math.sqrt(t.a*t.a+t.b*t.b),r=(Math.atan2(t.b,t.a)/S%360+360)%360;return{l:t.L,c:n,h:r}}function tt(t){const n=p(t.c,4);return{l:p(t.l,3),c:n,h:n===0?0:p(t.h,1)}}function f(t){return Math.round(g(t)*255)}function d(t){const n=Z(Q(t)),r=t.r===t.g&&t.g===t.b?{l:n.l,c:0,h:0}:n,e=tt(r);if(x(e)){const o=_(e);if(f(o.r)===f(t.r)&&f(o.g)===f(t.g)&&f(o.b)===f(t.b))return e}return r}function nt(t){const n=t.slice(1);if(!/^[0-9a-f]+$/i.test(n))return null;if(n.length===3){const[r,e,o]=n.split("").map(u=>parseInt(u+u,16));return{r:r/255,g:e/255,b:o/255}}return n.length===6?{r:parseInt(n.slice(0,2),16)/255,g:parseInt(n.slice(2,4),16)/255,b:parseInt(n.slice(4,6),16)/255}:null}function F(t,n){const r=t.match(new RegExp("^"+n+"\\("+i+"*([^)]*?)"+i+"*\\)$","i"));if(!r)return null;const e=r[1];if(e.includes("/"))return null;const o=e.includes(","),u=e.split(o?X:y);return u.length!==3||u.some(c=>c.length===0)?null:{args:u,legacy:o}}const rt=new RegExp("^("+m+")([a-z%]*)$","i");function D(t){const n=t.match(rt);if(!n)return null;const r=parseFloat(n[1]);return isFinite(r)?{value:r,unit:n[2].toLowerCase()}:null}function et(t){if(t.unit!==""&&t.unit!=="%")return null;const n=t.unit==="%"?t.value/100:t.value/255;return Math.max(0,Math.min(1,n))}function ot(t){const n=L[t.unit];return n===void 0?null:t.value*n}function N(t){return t.unit!==""&&t.unit!=="%"?null:Math.max(0,Math.min(1,t.value/100))}function ut(t,n,r){const e=(t%360+360)%360,o=u=>{const c=(u+e/30)%12,s=n*Math.min(r,1-r);return r-s*Math.max(-1,Math.min(c-3,9-c,1))};return{r:o(0),g:o(8),b:o(4)}}const it='"#rrggbb", "#rgb", "rgb(\u2026)", "hsl(\u2026)", "oklch(\u2026)"';function lt(t){const n=G(t);if(n.startsWith("#")){const r=nt(n);return r?d(r):null}if(/^oklch\(/i.test(n))return q(n);if(/^rgba?\(/i.test(n)){const r=F(n,"rgba?");if(!r)return null;const e=r.args.map(D);if(e.some(l=>l===null))return null;const o=e;if(r.legacy&&new Set(o.map(l=>l.unit)).size>1)return null;const u=o.map(et);if(u.some(l=>l===null))return null;const[c,s,a]=u;return d({r:c,g:s,b:a})}if(/^hsla?\(/i.test(n)){const r=F(n,"hsla?");if(!r)return null;const e=r.args.map(D);if(e.some(v=>v===null))return null;const[o,u,c]=e;if(r.legacy&&(u.unit!=="%"||c.unit!=="%"))return null;const s=ot(o),a=N(u),l=N(c);return s===null||a===null||l===null?null:d(ut(s,a,l))}return null}function p(t,n){const r=Math.pow(10,n);return Math.round(t*r)/r}export{it as ACCEPTED_COLOR_FORMS,I as apcaContrast,K as clampChromaAndGamutMap,J as deriveSemantic,at as deriveSemanticWithContrast,j as ensureContrast,M as gamutMapToSRGB,x as isInSRGBGamut,_ as oklchToSRGB,lt as parseCssColor,q as parseOklch,st as rotateHue,ct as serializeOklch};
@@ -1,4 +1,4 @@
1
- var p=function(f,e,t,o){var r=arguments.length,s=r<3?e:o===null?o=Object.getOwnPropertyDescriptor(e,t):o,a;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")s=Reflect.decorate(f,e,t,o);else for(var c=f.length-1;c>=0;c--)(a=f[c])&&(s=(r<3?a(s):r>3?a(e,t,s):a(e,t))||s);return r>3&&s&&Object.defineProperty(e,t,s),s};import{css as E,LitElement as x}from"lit";import{property as y,state as U}from"lit/decorators.js";import{subscribeToRootEvent as g}from"./root-event-subscription.js";import{traverseToClosest as V}from"./utilities.js";import{parseOklch as A,serializeOklch as k,gamutMapToSRGB as O,deriveSemantic as L,deriveSemanticWithContrast as F}from"./color-engine.js";import{computeVariants as T}from"../root/helpers/compute-variants.js";import{SEMANTIC_COLOR_NAMES as S,semanticToCSS as P}from"./theme.js";import{alignAttributeTextInheritance as _,focusRing as z}from"./style-fragments.js";class n extends x{constructor(){super(...arguments),this.seedColorBacker="oklch(0.7 0.125 216)",this.espRoot=null,this.variantTokenOriginalValues=new Map,this.rootEventSubscriptionsActive=!1,this.subscribedRoot=null,this.rootEventUnsubscribers=[],this.variantBacker="primary",this.correlationId=globalThis.crypto?.randomUUID?.()??Math.random().toString(36),this.scheme="light",this.handleSeedColorChanged=e=>{this.syncRootFromDom(!1)&&(this.seedColor=e.seedColor,this.applyVariantTokens())},this.handleSchemeChanged=e=>{!this.syncRootFromDom(!1)||this.scheme===e.scheme||(this.scheme=e.scheme,this.applyVariantTokens())},this.handleThemeChanged=()=>{this.syncRootFromDom(!1)&&this.applyVariantTokens()},this.handleIconSpriteUrlChanged=()=>{this.syncRootFromDom(!1)&&this.requestUpdate()}}get seedColor(){return this.seedColorBacker}set seedColor(e){this.seedColorBacker=e}focusResolvedElementAfterUpdate(e,t){const o=()=>{const r=e();return r?(r.focus(t),!0):!1};o()||this.updateComplete.then(()=>{o()})}focusShadowElementAfterUpdate(e,t){this.focusResolvedElementAfterUpdate(()=>this.shadowRoot?.querySelector(e),t)}emitValueChanged(e){this.dispatchEvent(new CustomEvent("value-changed",{detail:e,bubbles:!0,composed:!0}))}get variant(){return this.variantBacker}set variant(e){this.variantBacker=e,this.applyVariantTokens()}connectedCallback(){super.connectedCallback();const e=this.syncRootFromDom(!1);e&&this.subscribeToRootEvents(e)}disconnectedCallback(){super.disconnectedCallback(),this.unsubscribeFromRootEvents()}firstUpdated(e){this.syncRootFromDom(!0)}syncRootFromDom(e){const t=V(this,"esp-root");if(!t){if(this.espRoot&&this.clearVariantTokens(),this.unsubscribeFromRootEvents(),this.espRoot=null,!e)return null;throw new Error("No esp-root ancestor found. Espalier components must be placed inside an <esp-root> element.")}const o=t!==this.espRoot,s=t.scheme==="dark"?"dark":"light",a=this.scheme!==s,c=this.seedColor!==t.seedColor;return this.espRoot=t,o&&this.isConnected&&this.subscribeToRootEvents(t),(o||a||c)&&(this.scheme=s,this.seedColor=t.seedColor,this.applyVariantTokens()),o&&this.requestUpdate(),t}subscribeToRootEvents(e){this.rootEventSubscriptionsActive&&this.subscribedRoot===e||(this.unsubscribeFromRootEvents(),this.subscribedRoot=e,this.rootEventUnsubscribers=[g(e,"seed-color-changed",this.handleSeedColorChanged),g(e,"scheme-changed",this.handleSchemeChanged),g(e,"theme-changed",this.handleThemeChanged),g(e,"icon-sprite-url-changed",this.handleIconSpriteUrlChanged)],this.rootEventSubscriptionsActive=!0)}unsubscribeFromRootEvents(){if(this.rootEventSubscriptionsActive){for(const e of this.rootEventUnsubscribers)e();this.rootEventUnsubscribers=[],this.subscribedRoot=null,this.rootEventSubscriptionsActive=!1}}traverseToClosest(e){return V(this,e)}applyVariantTokens(){if(!this.espRoot)return;const e=this.getVariantColorSource();if(!e){this.clearVariantTokens();return}const t=this.espRoot.activeTheme,o=A(t.seedColor);if(!o)return;const s=T(o,t)[e];if(!s){this.clearVariantTokens();return}this.setVariantTokenProperty("--esp-color-primary",k(O(s)));const a=T(s,t),c=n.statusVariantSources.has(e),{textContrast:C}=n,b={};for(const i of S){if(C[i])continue;const l=t.semanticMappings[i],h=t.chroma[i],d=this.effectiveVariantTokenSource(i,l.source,c),v=a[d],m=t.lightness[l.lightness],u=L(v,m,h.min,h.max);b[i]=u,this.setVariantTokenProperty(P(i),k(u))}for(const i of S){const l=C[i];if(!l)continue;const h=t.semanticMappings[i],d=t.chroma[i],v=this.effectiveVariantTokenSource(i,h.source,c),m=a[v],u=t.lightness[h.lightness],w=b[l.bg],R=F(m,u,d.min,d.max,w,l.targetLc);b[i]=R,this.setVariantTokenProperty(P(i),k(R))}}effectiveVariantTokenSource(e,t,o){return o&&n.semanticActionTokens.has(e)?"primary":t}getVariantColorSource(){switch(this.variant){case"":case"primary":case"neutral":return"";case"info":return"complementary";default:return this.variant}}setVariantTokenProperty(e,t){const o=this.variantTokenOriginalValues.get(e);if(o){const r=this.style.getPropertyValue(e),s=this.style.getPropertyPriority(e);(r!==o.generatedValue||s!==o.generatedPriority)&&(o.originalValue=r.length?r:null,o.originalPriority=s),o.generatedValue=t,o.generatedPriority=""}else{const r=this.style.getPropertyValue(e);this.variantTokenOriginalValues.set(e,{generatedPriority:"",generatedValue:t,originalPriority:this.style.getPropertyPriority(e),originalValue:r.length?r:null})}this.style.setProperty(e,t)}clearVariantTokens(){for(const[e,t]of this.variantTokenOriginalValues){const o=this.style.getPropertyValue(e),r=this.style.getPropertyPriority(e);(o!==t.generatedValue||r!==t.generatedPriority)&&(t.originalValue=o.length?o:null,t.originalPriority=r),t.originalValue===null?this.style.removeProperty(e):this.style.setProperty(e,t.originalValue,t.originalPriority)}this.variantTokenOriginalValues.clear()}}n.textContrast={text:{bg:"background",targetLc:75},dangerText:{bg:"background",targetLc:75},headings:{bg:"background",targetLc:60},headingsHover:{bg:"background",targetLc:60},link:{bg:"background",targetLc:75},linkHover:{bg:"background",targetLc:75},actionText:{bg:"actionBackground",targetLc:75},inputCaret:{bg:"layer2",targetLc:60},inputSelection:{bg:"inputSelectionBg",targetLc:60}},n.statusVariantSources=new Set(["danger","success","warning"]),n.semanticActionTokens=new Set(["actionBackground","actionText"]),n.styles=[z(".esp-field:focus-within","--esp-field-focus-shadow"),_,E`
1
+ var p=function(f,e,t,o){var r=arguments.length,s=r<3?e:o===null?o=Object.getOwnPropertyDescriptor(e,t):o,a;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")s=Reflect.decorate(f,e,t,o);else for(var c=f.length-1;c>=0;c--)(a=f[c])&&(s=(r<3?a(s):r>3?a(e,t,s):a(e,t))||s);return r>3&&s&&Object.defineProperty(e,t,s),s};import{css as x,LitElement as U}from"lit";import{property as y,state as A}from"lit/decorators.js";import{subscribeToRootEvent as g}from"./root-event-subscription.js";import{traverseToClosest as T}from"./utilities.js";import{parseCssColor as L,serializeOklch as k,gamutMapToSRGB as O,deriveSemantic as F,deriveSemanticWithContrast as _}from"./color-engine.js";import{computeVariants as S,resolveMappingSource as z}from"../root/helpers/compute-variants.js";import{SEMANTIC_COLOR_NAMES as P,semanticToCSS as w}from"./theme.js";import{alignAttributeTextInheritance as D,focusRing as B}from"./style-fragments.js";class n extends U{constructor(){super(...arguments),this.seedColorBacker="oklch(0.7 0.125 216)",this.espRoot=null,this.variantTokenOriginalValues=new Map,this.rootEventSubscriptionsActive=!1,this.subscribedRoot=null,this.rootEventUnsubscribers=[],this.variantBacker="primary",this.correlationId=globalThis.crypto?.randomUUID?.()??Math.random().toString(36),this.scheme="light",this.handleSeedColorChanged=e=>{this.syncRootFromDom(!1)&&(this.seedColor=e.seedColor,this.applyVariantTokens())},this.handleSchemeChanged=e=>{!this.syncRootFromDom(!1)||this.scheme===e.scheme||(this.scheme=e.scheme,this.applyVariantTokens())},this.handleThemeChanged=()=>{this.syncRootFromDom(!1)&&this.applyVariantTokens()},this.handleIconSpriteUrlChanged=()=>{this.syncRootFromDom(!1)&&this.requestUpdate()}}get seedColor(){return this.seedColorBacker}set seedColor(e){this.seedColorBacker=e}focusResolvedElementAfterUpdate(e,t){const o=()=>{const r=e();return r?(r.focus(t),!0):!1};o()||this.updateComplete.then(()=>{o()})}focusShadowElementAfterUpdate(e,t){this.focusResolvedElementAfterUpdate(()=>this.shadowRoot?.querySelector(e),t)}emitValueChanged(e){this.dispatchEvent(new CustomEvent("value-changed",{detail:e,bubbles:!0,composed:!0}))}get variant(){return this.variantBacker}set variant(e){this.variantBacker=e,this.applyVariantTokens()}connectedCallback(){super.connectedCallback();const e=this.syncRootFromDom(!1);e&&this.subscribeToRootEvents(e)}disconnectedCallback(){super.disconnectedCallback(),this.unsubscribeFromRootEvents()}firstUpdated(e){this.syncRootFromDom(!0)}syncRootFromDom(e){const t=T(this,"esp-root");if(!t){if(this.espRoot&&this.clearVariantTokens(),this.unsubscribeFromRootEvents(),this.espRoot=null,!e)return null;throw new Error("No esp-root ancestor found. Espalier components must be placed inside an <esp-root> element.")}const o=t!==this.espRoot,s=t.scheme==="dark"?"dark":"light",a=this.scheme!==s,c=this.seedColor!==t.seedColor;return this.espRoot=t,o&&this.isConnected&&this.subscribeToRootEvents(t),(o||a||c)&&(this.scheme=s,this.seedColor=t.seedColor,this.applyVariantTokens()),o&&this.requestUpdate(),t}subscribeToRootEvents(e){this.rootEventSubscriptionsActive&&this.subscribedRoot===e||(this.unsubscribeFromRootEvents(),this.subscribedRoot=e,this.rootEventUnsubscribers=[g(e,"seed-color-changed",this.handleSeedColorChanged),g(e,"scheme-changed",this.handleSchemeChanged),g(e,"theme-changed",this.handleThemeChanged),g(e,"icon-sprite-url-changed",this.handleIconSpriteUrlChanged)],this.rootEventSubscriptionsActive=!0)}unsubscribeFromRootEvents(){if(this.rootEventSubscriptionsActive){for(const e of this.rootEventUnsubscribers)e();this.rootEventUnsubscribers=[],this.subscribedRoot=null,this.rootEventSubscriptionsActive=!1}}traverseToClosest(e){return T(this,e)}applyVariantTokens(){if(!this.espRoot)return;const e=this.getVariantColorSource();if(!e){this.clearVariantTokens();return}const t=this.espRoot.activeTheme,o=L(t.seedColor);if(!o)return;const s=S(o,t)[e];if(!s){this.clearVariantTokens();return}this.setVariantTokenProperty("--esp-color-primary",k(O(s)));const a=S(s,t),c=n.statusVariantSources.has(e),{textContrast:C}=n,b={},R=i=>z(i,a,t.anchors)??a.primary;for(const i of P){if(C[i])continue;const l=t.semanticMappings[i],h=t.chroma[i],d=this.effectiveVariantTokenSource(i,l.source,c),v=R(d),m=t.lightness[l.lightness],u=F(v,m,h.min,h.max);b[i]=u,this.setVariantTokenProperty(w(i),k(u))}for(const i of P){const l=C[i];if(!l)continue;const h=t.semanticMappings[i],d=t.chroma[i],v=this.effectiveVariantTokenSource(i,h.source,c),m=R(v),u=t.lightness[h.lightness],E=b[l.bg],V=_(m,u,d.min,d.max,E,l.targetLc);b[i]=V,this.setVariantTokenProperty(w(i),k(V))}}effectiveVariantTokenSource(e,t,o){return o&&n.semanticActionTokens.has(e)?"primary":t}getVariantColorSource(){switch(this.variant){case"":case"primary":case"neutral":return"";case"info":return"complementary";default:return this.variant}}setVariantTokenProperty(e,t){const o=this.variantTokenOriginalValues.get(e);if(o){const r=this.style.getPropertyValue(e),s=this.style.getPropertyPriority(e);(r!==o.generatedValue||s!==o.generatedPriority)&&(o.originalValue=r.length?r:null,o.originalPriority=s),o.generatedValue=t,o.generatedPriority=""}else{const r=this.style.getPropertyValue(e);this.variantTokenOriginalValues.set(e,{generatedPriority:"",generatedValue:t,originalPriority:this.style.getPropertyPriority(e),originalValue:r.length?r:null})}this.style.setProperty(e,t)}clearVariantTokens(){for(const[e,t]of this.variantTokenOriginalValues){const o=this.style.getPropertyValue(e),r=this.style.getPropertyPriority(e);(o!==t.generatedValue||r!==t.generatedPriority)&&(t.originalValue=o.length?o:null,t.originalPriority=r),t.originalValue===null?this.style.removeProperty(e):this.style.setProperty(e,t.originalValue,t.originalPriority)}this.variantTokenOriginalValues.clear()}}n.textContrast={text:{bg:"background",targetLc:75},dangerText:{bg:"background",targetLc:75},headings:{bg:"background",targetLc:60},headingsHover:{bg:"background",targetLc:60},link:{bg:"background",targetLc:75},linkHover:{bg:"background",targetLc:75},actionText:{bg:"actionBackground",targetLc:75},inputCaret:{bg:"layer2",targetLc:60},inputSelection:{bg:"inputSelectionBg",targetLc:60}},n.statusVariantSources=new Set(["danger","success","warning"]),n.semanticActionTokens=new Set(["actionBackground","actionText"]),n.styles=[B(".esp-field:focus-within","--esp-field-focus-shadow"),D,x`
2
2
  :host {
3
3
 
4
4
  --_esp-field-resolved-hover-bg: var(
@@ -122,4 +122,4 @@ var p=function(f,e,t,o){var r=arguments.length,s=r<3?e:o===null?o=Object.getOwnP
122
122
  .esp-field:has(textarea:disabled):hover {
123
123
  background-color: var(--esp-field-background, var(--esp-color-layer-2));
124
124
  }
125
- `],p([U()],n.prototype,"seedColor",null),p([y({attribute:!1})],n.prototype,"correlationId",void 0),p([y({type:String,reflect:!0})],n.prototype,"scheme",void 0),p([y({type:String,attribute:"variant",reflect:!0})],n.prototype,"variant",null);export{n as EspalierElementBase};
125
+ `],p([A()],n.prototype,"seedColor",null),p([y({attribute:!1})],n.prototype,"correlationId",void 0),p([y({type:String,reflect:!0})],n.prototype,"scheme",void 0),p([y({type:String,attribute:"variant",reflect:!0})],n.prototype,"variant",null);export{n as EspalierElementBase};
@@ -50,6 +50,79 @@ export type ColorSource = "primary" | "analogous-left" | "analogous-right" | "co
50
50
  * color's chroma.
51
51
  */
52
52
  export type VariantColorSource = Exclude<ColorSource, "primary">;
53
+ /**
54
+ * The object form of an anchor: a required base `color` plus named
55
+ * sub-slots — per-family variants the way designers already specify
56
+ * them (`rose.text` for the deepened rose that may carry copy).
57
+ */
58
+ export type ThemeAnchorSlots = {
59
+ color: string;
60
+ } & Record<string, string>;
61
+ /**
62
+ * A named brand color in a **resolved** theme.
63
+ *
64
+ * Either a color string, or the slot object — which always carries its
65
+ * base `color`, because a partial that names only slots refines an
66
+ * anchor rather than replacing it. Like `seedColor`, this type states
67
+ * the contract `validateTheme` enforces: a theme assembled from an
68
+ * unvalidated partial that never declared a base color reports an error
69
+ * there, and degrades to the seed at runtime.
70
+ *
71
+ * Every value accepts any CSS color form (ESP0161) and is normalized to
72
+ * OKLCH at the merge boundary.
73
+ */
74
+ export type ThemeAnchor = string | ThemeAnchorSlots;
75
+ /**
76
+ * A named brand color in a **partial** theme, where an object form may
77
+ * name slots alone — `{ rose: { hover: "#88404c" } }` refines the rose
78
+ * anchor a base theme already declared.
79
+ */
80
+ export type PartialThemeAnchor = string | Record<string, string>;
81
+ /** Anchors as they appear in a partial theme. */
82
+ export type PartialThemeAnchors = Record<string, PartialThemeAnchor>;
83
+ /**
84
+ * Named brand colors, keyed by slug.
85
+ *
86
+ * Anchors are free-standing color sources for semantic mappings —
87
+ * `source: "anchor:<name>"` — so a multi-color brand is declared as the
88
+ * swatches the designer handed over instead of being bent through hue
89
+ * geometry and per-token chroma clamps. See ADR-015.
90
+ */
91
+ export type ThemeAnchors = Record<string, ThemeAnchor>;
92
+ /**
93
+ * A semantic mapping's color source: a geometric or status family from
94
+ * {@link ColorSource}, or a declared anchor — `anchor:<name>` for its
95
+ * base color, `anchor:<name>.<slot>` for a sub-slot.
96
+ *
97
+ * An anchor source contributes its own hue **and chroma**; lightness
98
+ * always comes from the mapping's ramp stop, and APCA enforcement
99
+ * applies unchanged. Under an element variant, anchor sources stay
100
+ * absolute — a brand color is a color, not a relationship to the seed,
101
+ * so variant re-seeding does not rotate it.
102
+ */
103
+ export type MappingSource = ColorSource | `anchor:${string}`;
104
+ /** Anchor names and slot names share one slug grammar. */
105
+ export declare const ANCHOR_SLUG_PATTERN: RegExp;
106
+ /** A parsed `anchor:` mapping source. */
107
+ export interface AnchorReference {
108
+ name: string;
109
+ slot?: string;
110
+ }
111
+ /**
112
+ * Parse an `anchor:` mapping source into its reference, or return
113
+ * `null` for anything that is not anchor syntax at all. (A reference
114
+ * with an invalid or undeclared name parses fine here — declaration
115
+ * checks belong to validateTheme and resolution.)
116
+ */
117
+ export declare function parseAnchorSource(source: string): AnchorReference | null;
118
+ /**
119
+ * Resolve an anchor reference to its declared color string.
120
+ *
121
+ * `anchor:<name>` on an object-form anchor resolves the `color` key; a
122
+ * slot reference into a string-form anchor has nowhere to point and
123
+ * resolves `null`, as do unknown names and slots.
124
+ */
125
+ export declare function resolveAnchorColor(anchors: ThemeAnchors, reference: AnchorReference): string | null;
53
126
  /** Every semantic color token the system computes. */
54
127
  export type SemanticColorName = "background" | "layer1" | "layer2" | "layer3" | "layer4" | "actionBackground" | "actionText" | "border" | "shadow" | "text" | "dangerText" | "headings" | "headingsHover" | "link" | "linkHover" | "linkHoverBg" | "inputCaret" | "inputSelection" | "inputSelectionBg";
55
128
  /** Chroma range enforced on a semantic token before gamut mapping. */
@@ -65,8 +138,11 @@ export interface ChromaRange {
65
138
  * lightness ramp position sets the perceived brightness.
66
139
  */
67
140
  export interface SemanticMapping {
68
- /** The color variant or semantic hue to sample. */
69
- source: ColorSource;
141
+ /**
142
+ * The color source to sample: a geometric/status family, or a
143
+ * declared anchor as `anchor:<name>` / `anchor:<name>.<slot>`.
144
+ */
145
+ source: MappingSource;
70
146
  /** The lightness ramp position to apply. */
71
147
  lightness: LightnessKey;
72
148
  }
@@ -74,7 +150,14 @@ export interface SemanticMapping {
74
150
  export type SemanticMappings = Record<SemanticColorName, SemanticMapping>;
75
151
  /** The complete, resolved Espalier theme. */
76
152
  export interface EspalierTheme {
77
- /** OKLCH seed color string — drives the entire palette. */
153
+ /**
154
+ * Seed color — drives the entire palette.
155
+ *
156
+ * A theme author may supply any common CSS color form (`#rrggbb`,
157
+ * `#rgb`, `rgb()`, `hsl()`, or `oklch()`); non-OKLCH forms are
158
+ * converted at the merge boundary, so a **resolved** theme always
159
+ * carries an `oklch()` string here.
160
+ */
78
161
  seedColor: string;
79
162
  /** CSS `font-family` for body / UI text. */
80
163
  fontBody: string;
@@ -194,6 +277,13 @@ export interface EspalierTheme {
194
277
  chroma: Record<SemanticColorName, ChromaRange>;
195
278
  /** Maps each semantic token to its color source + lightness. */
196
279
  semanticMappings: SemanticMappings;
280
+ /**
281
+ * Named brand colors available to semantic mappings as
282
+ * `anchor:<name>` sources. Empty by default — a single-color brand
283
+ * needs none; a multi-color brand declares its swatches here instead
284
+ * of bending hue angles. See {@link ThemeAnchors} and ADR-015.
285
+ */
286
+ anchors: ThemeAnchors;
197
287
  /** Optional CSS `background-image` for the page surface. */
198
288
  pageBackgroundImage?: string;
199
289
  /** Opacity (0–1) for the page background image. */
@@ -209,8 +299,16 @@ export interface EspalierTheme {
209
299
  /** Opacity (0–1) for the vellum background image layer. */
210
300
  vellumBackgroundImageOpacity?: number;
211
301
  }
212
- /** Recursively-partial version of {@link EspalierTheme}. */
213
- export type PartialTheme = DeepPartial<EspalierTheme>;
302
+ /**
303
+ * Recursively-partial version of {@link EspalierTheme}.
304
+ *
305
+ * `anchors` is stated explicitly rather than derived: a partial may
306
+ * carry slot-only anchor overrides, which the resolved
307
+ * {@link ThemeAnchor} deliberately does not permit.
308
+ */
309
+ export type PartialTheme = Omit<DeepPartial<EspalierTheme>, "anchors"> & {
310
+ anchors?: PartialThemeAnchors;
311
+ };
214
312
  /** Validation result returned by {@link validateTheme}. */
215
313
  export interface ThemeValidationResult {
216
314
  /** `true` when there are zero errors (warnings are allowed). */
@@ -340,7 +438,7 @@ export declare function validateTheme(base64: string): ThemeValidationResult;
340
438
  * and therefore need key-by-key merging instead of wholesale
341
439
  * replacement when combining two {@link PartialTheme} objects.
342
440
  */
343
- export declare const NESTED_THEME_KEYS: readonly ["angles", "chroma", "lightness", "semanticHues", "semanticMappings", "variantChroma"];
441
+ export declare const NESTED_THEME_KEYS: readonly ["anchors", "angles", "chroma", "lightness", "semanticHues", "semanticMappings", "variantChroma"];
344
442
  /**
345
443
  * Deep-merge two {@link PartialTheme} objects.
346
444
  *
@@ -1 +1 @@
1
- import{parseOklch as O}from"./color-engine.js";const h=["background","layer1","layer2","layer3","layer4","actionBackground","actionText","border","shadow","text","dangerText","headings","headingsHover","link","linkHover","linkHoverBg","inputCaret","inputSelection","inputSelectionBg"],$=["primary","analogous-left","analogous-right","complementary","split-complementary-left","split-complementary-right","triadic-left","triadic-right","danger","success","warning"],C=["analogous-left","analogous-right","complementary","split-complementary-left","split-complementary-right","triadic-left","triadic-right","danger","success","warning"],d=["surface","raised1","raised2","raised3","raised4","accent","muted","text","border","ink","shadow"],I={surface:.99,raised1:.97,raised2:.9,raised3:.8,raised4:.72,accent:.5,muted:.45,text:.35,border:.3,ink:.25,shadow:.2},T={surface:.15,raised1:.2,raised2:.3,raised3:.4,raised4:.36,accent:.6,muted:.75,text:.85,border:.7,ink:.95,shadow:.6},y={background:{source:"primary",lightness:"surface"},layer1:{source:"primary",lightness:"raised1"},layer2:{source:"primary",lightness:"raised2"},layer3:{source:"primary",lightness:"raised3"},layer4:{source:"primary",lightness:"raised4"},actionBackground:{source:"primary",lightness:"raised3"},actionText:{source:"primary",lightness:"ink"},border:{source:"primary",lightness:"border"},shadow:{source:"primary",lightness:"shadow"},text:{source:"primary",lightness:"text"},dangerText:{source:"danger",lightness:"text"},headings:{source:"primary",lightness:"muted"},headingsHover:{source:"primary",lightness:"text"},link:{source:"complementary",lightness:"accent"},linkHover:{source:"complementary",lightness:"text"},linkHoverBg:{source:"triadic-left",lightness:"raised2"},inputCaret:{source:"triadic-right",lightness:"ink"},inputSelection:{source:"complementary",lightness:"text"},inputSelectionBg:{source:"triadic-left",lightness:"raised2"}},f=.4;function b(){const i={};for(const e of h)i[e]={min:0,max:f};return i}const B={seedColor:"oklch(0.7 0.125 216)",fontBody:"",fontHeadings:"",fontBrand:"",fontMonospace:"",fontWeightBody:"normal",fontWeightHeadings:"bold",fontWeightBrand:"bold",fontWeightMonospace:"normal",stylesheets:[],rootFontSize:16,typeRatio:1.25,spaceRatio:1.618,borderRadius:.2,viewportMin:320,viewportMax:1200,angles:{analogous:30,complementary:180,splitComplementary:30,triadic:120},semanticHues:{danger:27,success:150,warning:90},variantChroma:{},chroma:b(),semanticMappings:{...y}},_={...B,chroma:b(),semanticMappings:{...y},lightness:{...I}},W={...B,chroma:b(),semanticMappings:{...y},lightness:{...T}},M=new Set(["__proto__","constructor","prototype"]);function l(i){return!M.has(i)}function w(i,e){return M.has(i)?void 0:e}function F(i){return`--esp-color-${i.replace(/([A-Z])/g,"-$1").replace(/(\d)/g,"-$1").toLowerCase()}`}function R(i){try{const e=atob(i),s=JSON.parse(e,w);return typeof s!="object"||s===null||Array.isArray(s)?null:s}catch{return null}}function k(i){return btoa(JSON.stringify(i))}function N(i,e){const s={...i,seedColor:e.seedColor??i.seedColor,fontBody:e.fontBody??i.fontBody,fontHeadings:e.fontHeadings??i.fontHeadings,fontBrand:e.fontBrand??i.fontBrand,fontMonospace:e.fontMonospace??i.fontMonospace,fontWeightBody:String(e.fontWeightBody??i.fontWeightBody),fontWeightHeadings:String(e.fontWeightHeadings??i.fontWeightHeadings),fontWeightBrand:String(e.fontWeightBrand??i.fontWeightBrand),fontWeightMonospace:String(e.fontWeightMonospace??i.fontWeightMonospace),stylesheets:e.stylesheets??[...i.stylesheets],rootFontSize:e.rootFontSize??i.rootFontSize,typeRatio:e.typeRatio??i.typeRatio,spaceRatio:e.spaceRatio??i.spaceRatio,borderRadius:e.borderRadius??i.borderRadius,viewportMin:e.viewportMin??i.viewportMin,viewportMax:e.viewportMax??i.viewportMax,angles:{...i.angles,...e.angles},semanticHues:{...i.semanticHues,...e.semanticHues},variantChroma:{...i.variantChroma,...e.variantChroma},lightness:{...i.lightness,...e.lightness},chroma:S(i.chroma,e.chroma),semanticMappings:S(i.semanticMappings,e.semanticMappings)};return e.pageBackgroundImage!==void 0&&(s.pageBackgroundImage=e.pageBackgroundImage),e.pageBackgroundImageOpacity!==void 0&&(s.pageBackgroundImageOpacity=e.pageBackgroundImageOpacity),e.boxBackgroundImage!==void 0&&(s.boxBackgroundImage=e.boxBackgroundImage),e.boxBackgroundImageOpacity!==void 0&&(s.boxBackgroundImageOpacity=e.boxBackgroundImageOpacity),e.vellumOpacity!==void 0&&(s.vellumOpacity=e.vellumOpacity),e.vellumBackgroundImage!==void 0&&(s.vellumBackgroundImage=e.vellumBackgroundImage),e.vellumBackgroundImageOpacity!==void 0&&(s.vellumBackgroundImageOpacity=e.vellumBackgroundImageOpacity),s}function S(i,e){if(!e)return{...i};const s={...i};for(const c of Object.keys(e)){const u=e[c];u!==void 0&&(s[c]=u)}return s}function L(i){const e=[],s=[];let c;try{c=atob(i)}catch{return e.push("Failed to decode Base64 string."),{valid:!1,errors:e,warnings:s}}let u;try{u=JSON.parse(c)}catch{return e.push("Decoded string is not valid JSON."),{valid:!1,errors:e,warnings:s}}if(typeof u!="object"||u===null||Array.isArray(u))return e.push("Theme must be a JSON object."),{valid:!1,errors:e,warnings:s};const o=u;"seedColor"in o&&(typeof o.seedColor!="string"?e.push("seedColor must be a string."):O(o.seedColor)||e.push(`seedColor is not a valid OKLCH value: "${o.seedColor}".`));for(const t of["fontBody","fontHeadings","fontBrand","fontMonospace"])t in o&&typeof o[t]!="string"&&e.push(`${t} must be a string.`);const g=["normal","bold","lighter","bolder"],p=["inherit","initial","unset","revert","revert-layer"];for(const t of["fontWeightBody","fontWeightHeadings","fontWeightBrand","fontWeightMonospace"])if(t in o){const n=o[t];if(typeof n=="number")(n<1||n>1e3)&&e.push(`${t} numeric value must be 1\u20131000 (got ${n}).`);else if(typeof n=="string"){const a=g.includes(n)||p.includes(n);if(/^\d+$/.test(n)){const x=Number(n);(x<1||x>1e3)&&e.push(`${t} numeric value must be 1\u20131000 (got "${n}").`)}else a||s.push(`${t} = "${n}" is not a standard font-weight value.`)}else e.push(`${t} must be a string or number.`)}"stylesheets"in o&&(Array.isArray(o.stylesheets)?o.stylesheets.some(t=>typeof t!="string")&&e.push("Every entry in stylesheets must be a string."):e.push("stylesheets must be an array of strings."));const m=[["rootFontSize",1,100],["borderRadius",0,10],["viewportMin",100,1e4],["viewportMax",200,1e4]];for(const[t,n,a]of m)if(t in o)if(typeof o[t]!="number"||!isFinite(o[t]))e.push(`${t} must be a finite number.`);else{const r=o[t];n!==void 0&&r<n&&e.push(`${t} must be \u2265 ${n} (got ${r}).`),a!==void 0&&r>a&&s.push(`${t} = ${r} is unusually high (max ${a}).`)}for(const t of["typeRatio","spaceRatio"])if(t in o)if(typeof o[t]!="number"||!isFinite(o[t]))e.push(`${t} must be a finite number.`);else{const n=o[t];n<=1&&e.push(`${t} must be > 1 (got ${n}).`);const a=t==="typeRatio"?1.3:2;n>a&&s.push(`${t} = ${n} is very high (max ${a}); scales may be extreme.`)}if("viewportMin"in o&&"viewportMax"in o){const t=o.viewportMin,n=o.viewportMax;typeof t=="number"&&typeof n=="number"&&t>=n&&e.push(`viewportMin (${t}) must be less than viewportMax (${n}).`)}if("angles"in o)if(typeof o.angles!="object"||o.angles===null)e.push("angles must be an object.");else{const t=o.angles;for(const n of["analogous","complementary","splitComplementary","triadic"])if(n in t)if(typeof t[n]!="number"||!isFinite(t[n]))e.push(`angles.${n} must be a finite number.`);else{const a=t[n];(a<0||a>360)&&s.push(`angles.${n} = ${a} is outside 0\u2013360.`)}}if("semanticHues"in o)if(typeof o.semanticHues!="object"||o.semanticHues===null)e.push("semanticHues must be an object.");else{const t=o.semanticHues;for(const n of["danger","success","warning"])if(n in t)if(typeof t[n]!="number"||!isFinite(t[n]))e.push(`semanticHues.${n} must be a finite number.`);else{const a=t[n];(a<0||a>360)&&s.push(`semanticHues.${n} = ${a} is outside 0\u2013360.`)}}if("variantChroma"in o)if(typeof o.variantChroma!="object"||o.variantChroma===null)e.push("variantChroma must be an object.");else{const t=o.variantChroma;for(const n of C)if(n in t)if(typeof t[n]!="number"||!isFinite(t[n]))e.push(`variantChroma["${n}"] must be a finite number.`);else{const a=t[n];a<0&&e.push(`variantChroma["${n}"] must be \u2265 0 (got ${a}).`),a>f&&s.push(`variantChroma["${n}"] = ${a} exceeds ${f}.`)}}if("lightness"in o)if(typeof o.lightness!="object"||o.lightness===null)e.push("lightness must be an object.");else{const t=o.lightness;for(const n of d)if(n in t)if(typeof t[n]!="number"||!isFinite(t[n]))e.push(`lightness.${n} must be a finite number.`);else{const a=t[n];(a<0||a>1)&&e.push(`lightness.${n} must be 0\u20131 (got ${a}).`)}}if("chroma"in o)if(typeof o.chroma!="object"||o.chroma===null)e.push("chroma must be an object.");else{const t=o.chroma;for(const n of h)if(n in t){const a=t[n];if(typeof a!="object"||a===null){e.push(`chroma.${n} must be { min, max }.`);continue}const r=a;(typeof r.min!="number"||r.min<0)&&e.push(`chroma.${n}.min must be \u2265 0.`),(typeof r.max!="number"||r.max<0||r.max>f)&&e.push(`chroma.${n}.max must be 0\u2013${f}.`),typeof r.min=="number"&&typeof r.max=="number"&&r.min>r.max&&e.push(`chroma.${n}.min (${r.min}) must be \u2264 max (${r.max}).`)}}if("semanticMappings"in o)if(typeof o.semanticMappings!="object"||o.semanticMappings===null)e.push("semanticMappings must be an object.");else{const t=o.semanticMappings;for(const n of h)if(n in t){const a=t[n];if(typeof a!="object"||a===null){e.push(`semanticMappings.${n} must be { source, lightness }.`);continue}const r=a;(typeof r.source!="string"||!$.includes(r.source))&&e.push(`semanticMappings.${n}.source must be one of: ${$.join(", ")}.`),(typeof r.lightness!="string"||!d.includes(r.lightness))&&e.push(`semanticMappings.${n}.lightness must be one of: ${d.join(", ")}.`)}}for(const t of["pageBackgroundImage","boxBackgroundImage","vellumBackgroundImage"])t in o&&typeof o[t]!="string"&&e.push(`${t} must be a string.`);for(const t of["pageBackgroundImageOpacity","boxBackgroundImageOpacity","vellumOpacity","vellumBackgroundImageOpacity"])if(t in o)if(typeof o[t]!="number"||!isFinite(o[t]))e.push(`${t} must be a finite number.`);else{const n=o[t];(n<0||n>1)&&e.push(`${t} must be 0\u20131 (got ${n}).`)}return{valid:e.length===0,errors:e,warnings:s}}const A=["angles","chroma","lightness","semanticHues","semanticMappings","variantChroma"];function E(i,e){const s={};for(const[c,u]of Object.entries(i))l(c)&&(s[c]=u);for(const[c,u]of Object.entries(e))u!==void 0&&l(c)&&(s[c]=u);for(const c of A){const u=i[c],o=e[c];if(u&&typeof u=="object"&&!Array.isArray(u)&&o&&typeof o=="object"&&!Array.isArray(o)){const g={};for(const[p,m]of Object.entries(u))l(p)&&(g[p]=m);for(const[p,m]of Object.entries(o))m!==void 0&&l(p)&&(g[p]=m);s[c]=g}}return s}function D(...i){let e={};for(const s of i){if(!s)continue;const c=R(s);c&&(e=E(e,c))}return k(e)}function v(i){return i.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\n/g,"\\n").replace(/\r/g,"\\r")}const H={borderRadius:.1,fontBody:'"Noto Sans", sans-serif',fontWeightBody:"normal",fontHeadings:'"Inika", serif',fontWeightHeadings:"normal",fontBrand:'"Inika", serif',fontWeightBrand:"normal",fontMonospace:'"JetBrains Mono", monospace',fontWeightMonospace:"normal",seedColor:"oklch(.07 0.15 216)"};function K(i){return k({...H,pageBackgroundImage:`url("${v(i)}")`,pageBackgroundImageOpacity:.5})}function U(i){return k({...H,pageBackgroundImage:`url("${v(i)}")`,pageBackgroundImageOpacity:.55})}export{$ as COLOR_SOURCES,T as DEFAULT_DARK_LIGHTNESS,W as DEFAULT_DARK_THEME,I as DEFAULT_LIGHT_LIGHTNESS,_ as DEFAULT_LIGHT_THEME,y as DEFAULT_SEMANTIC_MAPPINGS,d as LIGHTNESS_KEYS,A as NESTED_THEME_KEYS,h as SEMANTIC_COLOR_NAMES,C as VARIANT_COLOR_SOURCES,U as buildTaprootDarkTheme,K as buildTaprootLightTheme,k as encodeTheme,D as layerThemes,E as mergePartials,N as mergeTheme,R as parseTheme,F as semanticToCSS,L as validateTheme};
1
+ import{ACCEPTED_COLOR_FORMS as $,parseCssColor as b,parseOklch as _,serializeOklch as W}from"./color-engine.js";const A=/^[a-z][a-z0-9-]*$/,N=/^anchor:([^.]+)(?:\.(.+))?$/;function F(s){const e=N.exec(s);return e?e[2]===void 0?{name:e[1]}:{name:e[1],slot:e[2]}:null}function X(s,e){const i=s[e.name];if(i===void 0)return null;if(typeof i=="string")return e.slot===void 0?i:null;const r=i[e.slot??"color"];return typeof r=="string"?r:null}const k=["background","layer1","layer2","layer3","layer4","actionBackground","actionText","border","shadow","text","dangerText","headings","headingsHover","link","linkHover","linkHoverBg","inputCaret","inputSelection","inputSelectionBg"],x=["primary","analogous-left","analogous-right","complementary","split-complementary-left","split-complementary-right","triadic-left","triadic-right","danger","success","warning"],D=["analogous-left","analogous-right","complementary","split-complementary-left","split-complementary-right","triadic-left","triadic-right","danger","success","warning"],B=["surface","raised1","raised2","raised3","raised4","accent","muted","text","border","ink","shadow"],L={surface:.99,raised1:.97,raised2:.9,raised3:.8,raised4:.72,accent:.5,muted:.45,text:.35,border:.3,ink:.25,shadow:.2},U={surface:.15,raised1:.2,raised2:.3,raised3:.4,raised4:.36,accent:.6,muted:.75,text:.85,border:.7,ink:.95,shadow:.6},S={background:{source:"primary",lightness:"surface"},layer1:{source:"primary",lightness:"raised1"},layer2:{source:"primary",lightness:"raised2"},layer3:{source:"primary",lightness:"raised3"},layer4:{source:"primary",lightness:"raised4"},actionBackground:{source:"primary",lightness:"raised3"},actionText:{source:"primary",lightness:"ink"},border:{source:"primary",lightness:"border"},shadow:{source:"primary",lightness:"shadow"},text:{source:"primary",lightness:"text"},dangerText:{source:"danger",lightness:"text"},headings:{source:"primary",lightness:"muted"},headingsHover:{source:"primary",lightness:"text"},link:{source:"complementary",lightness:"accent"},linkHover:{source:"complementary",lightness:"text"},linkHoverBg:{source:"triadic-left",lightness:"raised2"},inputCaret:{source:"triadic-right",lightness:"ink"},inputSelection:{source:"complementary",lightness:"text"},inputSelectionBg:{source:"triadic-left",lightness:"raised2"}},d=.4;function M(){const s={};for(const e of k)s[e]={min:0,max:d};return s}const j={seedColor:"oklch(0.7 0.125 216)",fontBody:"",fontHeadings:"",fontBrand:"",fontMonospace:"",fontWeightBody:"normal",fontWeightHeadings:"bold",fontWeightBrand:"bold",fontWeightMonospace:"normal",stylesheets:[],rootFontSize:16,typeRatio:1.25,spaceRatio:1.618,borderRadius:.2,viewportMin:320,viewportMax:1200,angles:{analogous:30,complementary:180,splitComplementary:30,triadic:120},semanticHues:{danger:27,success:150,warning:90},variantChroma:{},chroma:M(),semanticMappings:{...S},anchors:{}},Z={...j,chroma:M(),semanticMappings:{...S},anchors:{},lightness:{...L}},q={...j,chroma:M(),semanticMappings:{...S},anchors:{},lightness:{...U}},H=new Set(["__proto__","constructor","prototype"]);function m(s){return!H.has(s)}function z(s,e){return H.has(s)?void 0:e}function Q(s){return`--esp-color-${s.replace(/([A-Z])/g,"-$1").replace(/(\d)/g,"-$1").toLowerCase()}`}function K(s){try{const e=atob(s),i=JSON.parse(e,z);return typeof i!="object"||i===null||Array.isArray(i)?null:i}catch{return null}}function O(s){return btoa(JSON.stringify(s))}function C(s){if(_(s))return s;const e=b(s);return e?W(e):s}function R(s,e){const i={};for(const[r,u]of Object.entries(s))m(r)&&(i[r]=u);if(!e)return i;for(const[r,u]of Object.entries(e)){if(u===void 0||!m(r))continue;const o=i[r];if(o!==void 0&&typeof u=="object"&&u!==null){const f={};if(typeof o=="string")f.color=o;else for(const[p,g]of Object.entries(o))m(p)&&(f[p]=g);for(const[p,g]of Object.entries(u))g!==void 0&&m(p)&&(f[p]=g);i[r]=f;continue}i[r]=u}return i}function J(s){const e={};for(const[i,r]of Object.entries(s)){if(!m(i))continue;if(typeof r=="string"){e[i]=C(r);continue}const u={};for(const[o,f]of Object.entries(r))m(o)&&(u[o]=typeof f=="string"?C(f):f);e[i]=u}return e}function ee(s,e){const i={...s,seedColor:typeof e.seedColor=="string"?C(e.seedColor):s.seedColor,fontBody:e.fontBody??s.fontBody,fontHeadings:e.fontHeadings??s.fontHeadings,fontBrand:e.fontBrand??s.fontBrand,fontMonospace:e.fontMonospace??s.fontMonospace,fontWeightBody:String(e.fontWeightBody??s.fontWeightBody),fontWeightHeadings:String(e.fontWeightHeadings??s.fontWeightHeadings),fontWeightBrand:String(e.fontWeightBrand??s.fontWeightBrand),fontWeightMonospace:String(e.fontWeightMonospace??s.fontWeightMonospace),stylesheets:e.stylesheets??[...s.stylesheets],rootFontSize:e.rootFontSize??s.rootFontSize,typeRatio:e.typeRatio??s.typeRatio,spaceRatio:e.spaceRatio??s.spaceRatio,borderRadius:e.borderRadius??s.borderRadius,viewportMin:e.viewportMin??s.viewportMin,viewportMax:e.viewportMax??s.viewportMax,angles:{...s.angles,...e.angles},semanticHues:{...s.semanticHues,...e.semanticHues},variantChroma:{...s.variantChroma,...e.variantChroma},lightness:{...s.lightness,...e.lightness},chroma:T(s.chroma,e.chroma),semanticMappings:T(s.semanticMappings,e.semanticMappings),anchors:J(R(s.anchors,e.anchors))};return e.pageBackgroundImage!==void 0&&(i.pageBackgroundImage=e.pageBackgroundImage),e.pageBackgroundImageOpacity!==void 0&&(i.pageBackgroundImageOpacity=e.pageBackgroundImageOpacity),e.boxBackgroundImage!==void 0&&(i.boxBackgroundImage=e.boxBackgroundImage),e.boxBackgroundImageOpacity!==void 0&&(i.boxBackgroundImageOpacity=e.boxBackgroundImageOpacity),e.vellumOpacity!==void 0&&(i.vellumOpacity=e.vellumOpacity),e.vellumBackgroundImage!==void 0&&(i.vellumBackgroundImage=e.vellumBackgroundImage),e.vellumBackgroundImageOpacity!==void 0&&(i.vellumBackgroundImageOpacity=e.vellumBackgroundImageOpacity),i}function T(s,e){if(!e)return{...s};const i={...s};for(const r of Object.keys(e)){const u=e[r];u!==void 0&&(i[r]=u)}return i}function ne(s){const e=[],i=[];let r;try{r=atob(s)}catch{return e.push("Failed to decode Base64 string."),{valid:!1,errors:e,warnings:i}}let u;try{u=JSON.parse(r)}catch{return e.push("Decoded string is not valid JSON."),{valid:!1,errors:e,warnings:i}}if(typeof u!="object"||u===null||Array.isArray(u))return e.push("Theme must be a JSON object."),{valid:!1,errors:e,warnings:i};const o=u;"seedColor"in o&&(typeof o.seedColor!="string"?e.push("seedColor must be a string."):b(o.seedColor)||e.push(`seedColor is not a valid CSS color: "${o.seedColor}". Accepted forms: ${$}.`));for(const n of["fontBody","fontHeadings","fontBrand","fontMonospace"])n in o&&typeof o[n]!="string"&&e.push(`${n} must be a string.`);const f=["normal","bold","lighter","bolder"],p=["inherit","initial","unset","revert","revert-layer"];for(const n of["fontWeightBody","fontWeightHeadings","fontWeightBrand","fontWeightMonospace"])if(n in o){const t=o[n];if(typeof t=="number")(t<1||t>1e3)&&e.push(`${n} numeric value must be 1\u20131000 (got ${t}).`);else if(typeof t=="string"){const a=f.includes(t)||p.includes(t);if(/^\d+$/.test(t)){const l=Number(t);(l<1||l>1e3)&&e.push(`${n} numeric value must be 1\u20131000 (got "${t}").`)}else a||i.push(`${n} = "${t}" is not a standard font-weight value.`)}else e.push(`${n} must be a string or number.`)}"stylesheets"in o&&(Array.isArray(o.stylesheets)?o.stylesheets.some(n=>typeof n!="string")&&e.push("Every entry in stylesheets must be a string."):e.push("stylesheets must be an array of strings."));const g=[["rootFontSize",1,100],["borderRadius",0,10],["viewportMin",100,1e4],["viewportMax",200,1e4]];for(const[n,t,a]of g)if(n in o)if(typeof o[n]!="number"||!isFinite(o[n]))e.push(`${n} must be a finite number.`);else{const c=o[n];t!==void 0&&c<t&&e.push(`${n} must be \u2265 ${t} (got ${c}).`),a!==void 0&&c>a&&i.push(`${n} = ${c} is unusually high (max ${a}).`)}for(const n of["typeRatio","spaceRatio"])if(n in o)if(typeof o[n]!="number"||!isFinite(o[n]))e.push(`${n} must be a finite number.`);else{const t=o[n];t<=1&&e.push(`${n} must be > 1 (got ${t}).`);const a=n==="typeRatio"?1.3:2;t>a&&i.push(`${n} = ${t} is very high (max ${a}); scales may be extreme.`)}if("viewportMin"in o&&"viewportMax"in o){const n=o.viewportMin,t=o.viewportMax;typeof n=="number"&&typeof t=="number"&&n>=t&&e.push(`viewportMin (${n}) must be less than viewportMax (${t}).`)}if("angles"in o)if(typeof o.angles!="object"||o.angles===null)e.push("angles must be an object.");else{const n=o.angles;for(const t of["analogous","complementary","splitComplementary","triadic"])if(t in n)if(typeof n[t]!="number"||!isFinite(n[t]))e.push(`angles.${t} must be a finite number.`);else{const a=n[t];(a<0||a>360)&&i.push(`angles.${t} = ${a} is outside 0\u2013360.`)}}if("semanticHues"in o)if(typeof o.semanticHues!="object"||o.semanticHues===null)e.push("semanticHues must be an object.");else{const n=o.semanticHues;for(const t of["danger","success","warning"])if(t in n)if(typeof n[t]!="number"||!isFinite(n[t]))e.push(`semanticHues.${t} must be a finite number.`);else{const a=n[t];(a<0||a>360)&&i.push(`semanticHues.${t} = ${a} is outside 0\u2013360.`)}}if("variantChroma"in o)if(typeof o.variantChroma!="object"||o.variantChroma===null)e.push("variantChroma must be an object.");else{const n=o.variantChroma;for(const t of D)if(t in n)if(typeof n[t]!="number"||!isFinite(n[t]))e.push(`variantChroma["${t}"] must be a finite number.`);else{const a=n[t];a<0&&e.push(`variantChroma["${t}"] must be \u2265 0 (got ${a}).`),a>d&&i.push(`variantChroma["${t}"] = ${a} exceeds ${d}.`)}}if("lightness"in o)if(typeof o.lightness!="object"||o.lightness===null)e.push("lightness must be an object.");else{const n=o.lightness;for(const t of B)if(t in n)if(typeof n[t]!="number"||!isFinite(n[t]))e.push(`lightness.${t} must be a finite number.`);else{const a=n[t];(a<0||a>1)&&e.push(`lightness.${t} must be 0\u20131 (got ${a}).`)}}if("chroma"in o)if(typeof o.chroma!="object"||o.chroma===null)e.push("chroma must be an object.");else{const n=o.chroma;for(const t of k)if(t in n){const a=n[t];if(typeof a!="object"||a===null){e.push(`chroma.${t} must be { min, max }.`);continue}const c=a;(typeof c.min!="number"||c.min<0)&&e.push(`chroma.${t}.min must be \u2265 0.`),(typeof c.max!="number"||c.max<0||c.max>d)&&e.push(`chroma.${t}.max must be 0\u2013${d}.`),typeof c.min=="number"&&typeof c.max=="number"&&c.min>c.max&&e.push(`chroma.${t}.min (${c.min}) must be \u2264 max (${c.max}).`)}}if("anchors"in o)if(typeof o.anchors!="object"||o.anchors===null||Array.isArray(o.anchors))e.push("anchors must be an object of named colors.");else for(const[n,t]of Object.entries(o.anchors))if(m(n)?A.test(n)||e.push(`anchors: "${n}" is not a valid anchor name; use a lowercase slug (letters, digits, hyphens).`):e.push(`anchors: "${n}" is a reserved JavaScript property name and cannot be an anchor name; rename it.`),x.includes(n)&&e.push(`anchors: "${n}" collides with a reserved color source name.`),typeof t=="string")b(t)||e.push(`anchors.${n} is not a valid CSS color: "${t}". Accepted forms: ${$}.`);else if(typeof t=="object"&&t!==null&&!Array.isArray(t)){const a=t;typeof a.color!="string"&&e.push(`anchors.${n} must declare its base "color".`);for(const[c,l]of Object.entries(a))m(c)?c!=="color"&&!A.test(c)&&e.push(`anchors.${n}: "${c}" is not a valid slot name; use a lowercase slug.`):e.push(`anchors.${n}: "${c}" is a reserved JavaScript property name and cannot be a slot name; rename it.`),typeof l!="string"?e.push(`anchors.${n}.${c} must be a CSS color string.`):b(l)||e.push(`anchors.${n}.${c} is not a valid CSS color: "${l}". Accepted forms: ${$}.`)}else e.push(`anchors.${n} must be a color string or a { color, \u2026slots } object.`);const y=new Map;if("anchors"in o&&typeof o.anchors=="object"&&o.anchors!==null&&!Array.isArray(o.anchors))for(const[n,t]of Object.entries(o.anchors))y.set(n,t);if("semanticMappings"in o)if(typeof o.semanticMappings!="object"||o.semanticMappings===null)e.push("semanticMappings must be an object.");else{const n=o.semanticMappings;for(const t of k)if(t in n){const a=n[t];if(typeof a!="object"||a===null){e.push(`semanticMappings.${t} must be { source, lightness }.`);continue}const c=a;if(typeof c.source!="string")e.push(`semanticMappings.${t}.source must be a string.`);else if(c.source.startsWith("anchor:")){const l=F(c.source);if(!l)e.push(`semanticMappings.${t}.source "${c.source}" is not valid anchor syntax; use anchor:<name> or anchor:<name>.<slot>.`);else if(y.has(l.name)){if(l.slot!==void 0){const h=y.get(l.name);if(typeof(typeof h=="object"&&h!==null&&!Array.isArray(h)?h[l.slot]:void 0)!="string"){const v=typeof h=="object"&&h!==null?Object.keys(h).filter(E=>E!=="color"):[];e.push(`semanticMappings.${t}.source references unknown slot "${l.slot}" on anchor "${l.name}". Declared slots: ${v.length>0?v.join(", "):"(none)"}.`)}}}else{const h=[...y.keys()];e.push(`semanticMappings.${t}.source references undeclared anchor "${l.name}". Declared anchors: ${h.length>0?h.join(", "):"(none)"}.`)}}else x.includes(c.source)||e.push(`semanticMappings.${t}.source must be one of: ${x.join(", ")}, or a declared anchor as anchor:<name> / anchor:<name>.<slot>.`);(typeof c.lightness!="string"||!B.includes(c.lightness))&&e.push(`semanticMappings.${t}.lightness must be one of: ${B.join(", ")}.`)}}for(const n of["pageBackgroundImage","boxBackgroundImage","vellumBackgroundImage"])n in o&&typeof o[n]!="string"&&e.push(`${n} must be a string.`);for(const n of["pageBackgroundImageOpacity","boxBackgroundImageOpacity","vellumOpacity","vellumBackgroundImageOpacity"])if(n in o)if(typeof o[n]!="number"||!isFinite(o[n]))e.push(`${n} must be a finite number.`);else{const t=o[n];(t<0||t>1)&&e.push(`${n} must be 0\u20131 (got ${t}).`)}return{valid:e.length===0,errors:e,warnings:i}}const G=["anchors","angles","chroma","lightness","semanticHues","semanticMappings","variantChroma"];function P(s,e){const i={};for(const[r,u]of Object.entries(s))m(r)&&(i[r]=u);for(const[r,u]of Object.entries(e))u!==void 0&&m(r)&&(i[r]=u);for(const r of G){const u=s[r],o=e[r];if(u&&typeof u=="object"&&!Array.isArray(u)&&o&&typeof o=="object"&&!Array.isArray(o)){if(r==="anchors"){i[r]=R(u,o);continue}const f={};for(const[p,g]of Object.entries(u))m(p)&&(f[p]=g);for(const[p,g]of Object.entries(o))g!==void 0&&m(p)&&(f[p]=g);i[r]=f}}return i}function te(...s){let e={};for(const i of s){if(!i)continue;const r=K(i);r&&(e=P(e,r))}return O(e)}function I(s){return s.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\n/g,"\\n").replace(/\r/g,"\\r")}const w={borderRadius:.1,fontBody:'"Noto Sans", sans-serif',fontWeightBody:"normal",fontHeadings:'"Inika", serif',fontWeightHeadings:"normal",fontBrand:'"Inika", serif',fontWeightBrand:"normal",fontMonospace:'"JetBrains Mono", monospace',fontWeightMonospace:"normal",seedColor:"oklch(.07 0.15 216)"};function oe(s){return O({...w,pageBackgroundImage:`url("${I(s)}")`,pageBackgroundImageOpacity:.5})}function se(s){return O({...w,pageBackgroundImage:`url("${I(s)}")`,pageBackgroundImageOpacity:.55})}export{A as ANCHOR_SLUG_PATTERN,x as COLOR_SOURCES,U as DEFAULT_DARK_LIGHTNESS,q as DEFAULT_DARK_THEME,L as DEFAULT_LIGHT_LIGHTNESS,Z as DEFAULT_LIGHT_THEME,S as DEFAULT_SEMANTIC_MAPPINGS,B as LIGHTNESS_KEYS,G as NESTED_THEME_KEYS,k as SEMANTIC_COLOR_NAMES,D as VARIANT_COLOR_SOURCES,se as buildTaprootDarkTheme,oe as buildTaprootLightTheme,O as encodeTheme,te as layerThemes,P as mergePartials,ee as mergeTheme,F as parseAnchorSource,K as parseTheme,X as resolveAnchorColor,Q as semanticToCSS,ne as validateTheme};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@taprootio/espalier",
3
- "version": "2.15.4",
3
+ "version": "2.17.0",
4
4
  "packageManager": "bun@1.3.12",
5
5
  "description": "Espalier — a themeable, accessible, framework-agnostic, enterprise-grade design system built on web standards and love.",
6
6
  "customElements": "custom-elements.json",