@taprootio/espalier 3.0.0 → 3.1.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.
- package/CHANGELOG.md +32 -0
- package/custom-elements.json +11247 -11192
- package/dist/shared/data-colors.d.ts +21 -0
- package/dist/shared/data-colors.js +1 -1
- package/dist/shared/esp-element-base.d.ts +3 -3
- package/dist/shared/esp-element-base.js +1 -1
- package/dist/shared/style-fragments.js +6 -6
- package/dist/shared/theme.d.ts +90 -17
- package/dist/shared/theme.js +1 -1
- package/dist/shared/variant-engine.js +1 -1
- package/espalier.token-manifest.json +5 -0
- package/package.json +5 -1
|
@@ -52,6 +52,27 @@ export interface DataPaletteIssue {
|
|
|
52
52
|
* the threshold.
|
|
53
53
|
*/
|
|
54
54
|
export declare function auditDataPalette(palette: Readonly<DataPalette>, threshold?: number): DataPaletteIssue[];
|
|
55
|
+
/** Vision conditions covered by {@link auditColorDistances}: normal plus every CVD simulation. */
|
|
56
|
+
export type VisionCondition = ColorVisionSimulation | "normal";
|
|
57
|
+
/** One too-close pair found by {@link auditColorDistances}. */
|
|
58
|
+
export interface ColorDistanceIssue {
|
|
59
|
+
/** The two entry names, in input order. */
|
|
60
|
+
pair: [string, string];
|
|
61
|
+
/** The vision condition under which the pair collapses. */
|
|
62
|
+
simulation: VisionCondition;
|
|
63
|
+
/** Post-simulation OKLab distance between the pair. */
|
|
64
|
+
distance: number;
|
|
65
|
+
/** The threshold the distance fell below. */
|
|
66
|
+
threshold: number;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Audit an arbitrary named color set for pairwise distinguishability
|
|
70
|
+
* under normal vision and every CVD simulation (ESP0172 — the intent
|
|
71
|
+
* collision check). Values must be concrete CSS colors, like
|
|
72
|
+
* {@link auditDataPalette}'s — resolve anchors first; the palette-shaped
|
|
73
|
+
* audit remains the categorical-series wrapper.
|
|
74
|
+
*/
|
|
75
|
+
export declare function auditColorDistances(entries: ReadonlyArray<readonly [string, string]>, threshold?: number, conditions?: readonly VisionCondition[]): ColorDistanceIssue[];
|
|
55
76
|
/** Minimum supported number of colors in a generated data ramp. */
|
|
56
77
|
export declare const MIN_DATA_RAMP_STEPS = 3;
|
|
57
78
|
/** Maximum supported number of colors in a generated data ramp. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{clampChannel as
|
|
1
|
+
import{clampChannel as x,gamutMapToSRGB as m,linearRgbToOklab as S,oklabToOklch as k,oklchToOklab as b,oklchToSRGB as P,parseCssColor as F,serializeOklch as E,srgbToLinearRGB as q}from"./color-engine.js";const p=["series1","series2","series3","series4","series5","series6","series7","series8"],G={series1:"#000000",series2:"#E69F00",series3:"#56B4E9",series4:"#009E73",series5:"#F0E442",series6:"#0072B2",series7:"#D55E00",series8:"#CC79A7"},A=["deuteranopia","protanopia","tritanopia"],T=.07,_={protanopia:[[.152286,1.052583,-.204868],[.114503,.786281,.099216],[-.003882,-.048116,1.051998]],deuteranopia:[[.367322,.860646,-.227968],[.280085,.672501,.047413],[-.01182,.04294,.968881]],tritanopia:[[1.255528,-.076749,-.178779],[-.078411,.930809,.147602],[.004733,.691367,.3039]]};function d(e,t){const s=P(m(e)),a=q(s),n=o=>x(o[0]*a.r+o[1]*a.g+o[2]*a.b);return{r:n(t[0]),g:n(t[1]),b:n(t[2])}}function R(e,t){return Math.hypot(e.L-t.L,e.a-t.a,e.b-t.b)}function g(e,t){const s=F(e);if(!s)throw new TypeError(`${t} is not a valid opaque CSS color: "${e}".`);return s}function U(e,t=T){if(!Number.isFinite(t)||t<0)throw new RangeError("Data-palette distance threshold must be a finite number \u2265 0.");const s=new Map;for(const n of p)s.set(n,g(e[n],`dataPalette.${n}`));const a=[];for(const n of A){const o=new Map;for(const r of p)o.set(r,S(d(s.get(r),_[n])));for(let r=0;r<p.length;r+=1)for(let i=r+1;i<p.length;i+=1){const l=p[r],c=p[i],u=R(o.get(l),o.get(c));u<t&&a.push({series:[l,c],simulation:n,distance:u,threshold:t})}}return a}const v=[[1,0,0],[0,1,0],[0,0,1]];function B(e,t=T,s=["normal",...A]){if(!Number.isFinite(t)||t<0)throw new RangeError("Color distance threshold must be a finite number \u2265 0.");const a=e.map(([r,i])=>[r,g(i,r)]),n=[],o=s.map(r=>[r,r==="normal"?v:_[r]]);for(const[r,i]of o){const l=a.map(([,c])=>S(d(c,i)));for(let c=0;c<e.length;c+=1)for(let u=c+1;u<e.length;u+=1){const f=R(l[c],l[u]);f<t&&n.push({pair:[e[c][0],e[u][0]],simulation:r,distance:f,threshold:t})}}return n}const D=3,I=11,L=7,C=1e-6,$="oklch(0.96 0 0)";function M(e,t){if(!Number.isInteger(e)||e<D||e>I)throw new RangeError(`Data-ramp steps must be an integer from ${D} through ${I}.`);if(t&&e%2===0)throw new RangeError("Diverging data-ramp steps must be odd so the neutral is the midpoint.")}function w(e,t){if(!Number.isFinite(e)||e<0||e>1)throw new RangeError(`${t} must be a finite number from 0 through 1.`)}function V(e,t={}){const s=g(e,"Sequential ramp source"),a=t.steps??L,n=t.lightnessStart??.95,o=t.lightnessEnd??.25;if(M(a,!1),w(n,"Sequential ramp lightnessStart"),w(o,"Sequential ramp lightnessEnd"),n<=o)throw new RangeError("Sequential ramp lightnessStart must be greater than lightnessEnd.");if((n-o)/(a-1)<=C)throw new RangeError(`Sequential ramp lightness bounds must leave more than ${C} lightness between serialized stops.`);return Array.from({length:a},(r,i)=>{const l=i/(a-1),c=n+(o-n)*l;return E(m({l:c,c:s.c,h:s.h}))})}function N(e,t,s){return{L:e.L+(t.L-e.L)*s,a:e.a+(t.a-e.a)*s,b:e.b+(t.b-e.b)*s}}function z(e,t,s={}){const a=g(e,"Diverging ramp start"),n=g(t,"Diverging ramp end"),o=g(s.neutral??$,"Diverging ramp neutral"),r=s.steps??L;M(r,!0);const i=(r-1)/2,l=b(a),c=b(o),u=b(n);return Array.from({length:r},(f,h)=>{if(h===i)return E(m(o));const O=h<i?N(l,c,h/i):N(c,u,(h-i)/i);return E(m(k(O)))})}export{A as COLOR_VISION_SIMULATIONS,p as DATA_SERIES_KEYS,G as DEFAULT_DATA_PALETTE,L as DEFAULT_DATA_RAMP_STEPS,$ as DEFAULT_DIVERGING_NEUTRAL,I as MAX_DATA_RAMP_STEPS,T as MIN_DATA_COLOR_DISTANCE,C as MIN_DATA_RAMP_LIGHTNESS_STEP,D as MIN_DATA_RAMP_STEPS,B as auditColorDistances,U as auditDataPalette,z as generateDivergingRamp,V as generateSequentialRamp};
|
|
@@ -43,9 +43,9 @@ export declare class EspalierElementBase extends LitElement implements SeedColor
|
|
|
43
43
|
scheme: "dark" | "light" | "";
|
|
44
44
|
/**
|
|
45
45
|
* The element's [intent](/espalier-guides/) — its meaning: `neutral`
|
|
46
|
-
* (no pin), `success`, `warning`,
|
|
47
|
-
* fixed status family
|
|
48
|
-
*
|
|
46
|
+
* (no pin), or `success`, `warning`, `danger`, `info` — each pinned
|
|
47
|
+
* to its fixed status family (blue for `info`), retunable per theme
|
|
48
|
+
* via `intents`. On token-emitting controls a non-neutral intent pins the
|
|
49
49
|
* filled-action pair to that family, derived over the governing
|
|
50
50
|
* zone's theme; class-styled chrome (badges, callouts, status pills)
|
|
51
51
|
* opts out of inline emission and renders its treatment from CSS
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var h=function(f,e,t,r){var o=arguments.length,s=o<3?e:r===null?r=Object.getOwnPropertyDescriptor(e,t):r,a;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")s=Reflect.decorate(f,e,t,r);else for(var i=f.length-1;i>=0;i--)(a=f[i])&&(s=(o<3?a(s):o>3?a(e,t,s):a(e,t))||s);return o>3&&s&&Object.defineProperty(e,t,s),s};import{css as R,LitElement as C}from"lit";import{property as p,state as S}from"lit/decorators.js";import{subscribeToRootEvent as u}from"./root-event-subscription.js";import{traverseToClosest as b}from"./utilities.js";import{parseCssColor as w,serializeOklch as x,gamutMapToSRGB as P}from"./color-engine.js";import{computeVariants as v}from"../root/helpers/compute-variants.js";import{computeSemanticProperties as m}from"../root/helpers/compute-semantic-properties.js";import{lightnessRampProperties as E}from"../root/helpers/lightness-ramp-properties.js";import{ROLE_NAMES as V,mergeTheme as U,semanticToCSS as A}from"./theme.js";import{alignAttributeTextInheritance as I,focusRing as O}from"./style-fragments.js";import{syncNormalizedAttribute as D}from"./attribute-helpers.js";import{INTENT_VARIANTS as y,normalizeIntentVariant as z}from"./intent-values.js";const k=new WeakMap;class n extends C{constructor(){super(...arguments),this.seedColorBacker="oklch(0.7 0.125 216)",this.espRoot=null,this.contextBacker="",this.scopedTokenOriginalValues=new Map,this.warnedUnknownContexts=new Set,this.pendingInitialThemeRoot=null,this.rootEventSubscriptionsActive=!1,this.subscribedRoot=null,this.rootEventUnsubscribers=[],this.intentBacker="neutral",this.intentEmitsTokens=!0,this.warnedUnknownIntents=new Set,this.correlationId=globalThis.crypto?.randomUUID?.()??Math.random().toString(36),this.scheme="light",this.handleSeedColorChanged=e=>{this.syncRootFromDom(!1)&&(this.seedColor=e.seedColor,this.applyScopedColorTokens())},this.handleSchemeChanged=e=>{!this.syncRootFromDom(!1)||this.scheme===e.scheme||(this.scheme=e.scheme,this.applyScopedColorTokens())},this.handleThemeChanged=()=>{this.syncRootFromDom(!1)&&this.applyScopedColorTokens()},this.handleIconSpriteUrlChanged=()=>{this.syncRootFromDom(!1)&&this.requestUpdate()}}get seedColor(){return this.seedColorBacker}set seedColor(e){this.seedColorBacker=e}focusResolvedElementAfterUpdate(e,t){const r=()=>{const o=e();return o?(o.focus(t),!0):!1};r()||this.updateComplete.then(()=>{r()})}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 intent(){return this.intentBacker}set intent(e){const t=typeof e=="string"?e.trim():"";t!==""&&!y.includes(t)&&!this.warnedUnknownIntents.has(t)&&(this.warnedUnknownIntents.add(t),console.warn(`Espalier intent: "${t}" is not an intent; expected one of ${y.join(", ")}. Treating it as "neutral".`));const r=this.intentBacker,o=z(e);D(this,"intent",o),o!==r&&(this.intentBacker=o,this.requestUpdate("intent",r),this.applyTokensWhenRootReady())}get context(){return this.contextBacker}set context(e){const t=e??"";t!==this.contextBacker&&(this.contextBacker=t,this.applyTokensWhenRootReady(),this.refreshDescendantIntentDerivations())}refreshDescendantIntentDerivations(){const e=new Set,t=o=>{for(const s of Array.from(o.children))r(s)},r=o=>{if(!e.has(o)){if(e.add(o),o instanceof n&&o.applyTokensWhenRootReady(),o.shadowRoot&&t(o.shadowRoot),o instanceof HTMLSlotElement)for(const s of o.assignedElements({flatten:!0}))r(s);t(o)}};t(this),this.shadowRoot&&t(this.shadowRoot)}static flattenedParent(e){return e instanceof Element&&e.assignedSlot?e.assignedSlot:e instanceof ShadowRoot?e.host:e.parentNode}resolveAncestorZoneTheme(e){let t=n.flattenedParent(this);for(;t;){if(t instanceof Element&&t.localName==="esp-root")return null;if(t instanceof n){const r=t.contextBacker.trim();if(r){const o=this.resolveNamedContextTheme(e,r);if(o)return o}}t=n.flattenedParent(t)}return null}connectedCallback(){super.connectedCallback();const e=this.syncRootFromDom(!1);e&&this.subscribeToRootEvents(e)}disconnectedCallback(){super.disconnectedCallback(),this.unsubscribeFromRootEvents(),this.clearScopedTokens(),this.espRoot=null}firstUpdated(e){this.syncRootFromDom(!0),this.applyTokensWhenRootReady()}syncRootFromDom(e){const t=b(this,"esp-root");if(!t){if(this.espRoot&&this.clearScopedTokens(),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 r=t!==this.espRoot,s=t.scheme==="dark"?"dark":"light",a=this.scheme!==s,i=this.seedColor!==t.seedColor;return this.espRoot=t,r&&this.isConnected&&this.subscribeToRootEvents(t),(r||a||i)&&(this.scheme=s,this.seedColor=t.seedColor,this.applyTokensWhenRootReady()),r&&this.requestUpdate(),t}applyTokensWhenRootReady(){const e=this.espRoot;if(e&&(!e.hasUpdated||e.isUpdatePending)){this.applyTokensAfterInitialRootUpdate(e);return}this.applyScopedColorTokens()}applyTokensAfterInitialRootUpdate(e){if(this.pendingInitialThemeRoot===e)return;this.pendingInitialThemeRoot=e;const t=e.updateComplete;if(!t){this.pendingInitialThemeRoot=null,this.applyScopedColorTokens();return}t.then(()=>{this.pendingInitialThemeRoot===e&&(this.pendingInitialThemeRoot=null),!(!this.isConnected||this.espRoot!==e)&&(this.scheme=e.scheme==="dark"?"dark":"light",this.seedColor=e.seedColor,this.applyScopedColorTokens())})}subscribeToRootEvents(e){this.rootEventSubscriptionsActive&&this.subscribedRoot===e||(this.unsubscribeFromRootEvents(),this.subscribedRoot=e,this.rootEventUnsubscribers=[u(e,"seed-color-changed",this.handleSeedColorChanged),u(e,"scheme-changed",this.handleSchemeChanged),u(e,"theme-changed",this.handleThemeChanged),u(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 b(this,e)}applyScopedColorTokens(){if(!this.espRoot)return;const e=this.intentEmitsTokens?n.intentColorSources[this.intentBacker]:"";if(!e&&!this.context.trim()){this.clearScopedTokens();return}const t=this.espRoot.activeTheme;if(!t){this.clearScopedTokens();return}const r=this.resolveContextTheme(t),o=r.theme,s=w(o.seedColor);if(!s)return;const a=v(s,o),i={};if(r.applied&&(Object.assign(i,m(o,a)),Object.assign(i,E(o))),e){let c=o;r.applied||(c=this.resolveAncestorZoneTheme(t)??o);const l=c===o?a:v(s,c),T=m(c,l,{effectiveSource:(g,d)=>n.semanticActionTokens.has(g)?e:d});i["--esp-color-primary"]=x(P(l[e]));for(const g of n.semanticActionTokens){const d=A(g);i[d]=T[d]}}this.applyScopedTokenProperties(i)}resolveContextTheme(e){const t=this.context.trim();if(!t)return{applied:!1,theme:e};const r=this.resolveNamedContextTheme(e,t);return r?{applied:!0,theme:r}:(this.warnedUnknownContexts.has(t)||(this.warnedUnknownContexts.add(t),console.warn(`Espalier context: "${t}" is not defined by the active theme; inheriting root tokens.`)),{applied:!1,theme:e})}resolveNamedContextTheme(e,t){const r=e.contexts&&Object.prototype.hasOwnProperty.call(e.contexts,t)?e.contexts[t]:void 0;if(!r)return null;let o=k.get(e);const s=o?.get(t);if(s)return s;const a={};for(const c of V){const l=r[c];l!==void 0&&(a[c]=l)}const i=U(e,{lightness:r.lightness,roles:a});return o||(o=new Map,k.set(e,o)),o.set(t,i),i}applyScopedTokenProperties(e){for(const t of this.scopedTokenOriginalValues.keys())t in e||this.restoreScopedTokenProperty(t);for(const[t,r]of Object.entries(e))this.setScopedTokenProperty(t,r)}setScopedTokenProperty(e,t){const r=this.scopedTokenOriginalValues.get(e);if(r){const o=this.style.getPropertyValue(e),s=this.style.getPropertyPriority(e);(o!==r.generatedValue||s!==r.generatedPriority)&&(r.originalValue=o.length?o:null,r.originalPriority=s),r.generatedValue=t,r.generatedPriority=""}else{const o=this.style.getPropertyValue(e);this.scopedTokenOriginalValues.set(e,{generatedPriority:"",generatedValue:t,originalPriority:this.style.getPropertyPriority(e),originalValue:o.length?o:null})}this.style.setProperty(e,t)}restoreScopedTokenProperty(e){const t=this.scopedTokenOriginalValues.get(e);if(!t)return;const r=this.style.getPropertyValue(e),o=this.style.getPropertyPriority(e);(r!==t.generatedValue||o!==t.generatedPriority)&&(t.originalValue=r.length?r:null,t.originalPriority=o),t.originalValue===null?this.style.removeProperty(e):this.style.setProperty(e,t.originalValue,t.originalPriority),this.scopedTokenOriginalValues.delete(e)}clearScopedTokens(){for(const e of[...this.scopedTokenOriginalValues.keys()])this.restoreScopedTokenProperty(e)}}n.intentColorSources={danger:"danger",info:"
|
|
1
|
+
var h=function(f,e,t,r){var o=arguments.length,s=o<3?e:r===null?r=Object.getOwnPropertyDescriptor(e,t):r,a;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")s=Reflect.decorate(f,e,t,r);else for(var i=f.length-1;i>=0;i--)(a=f[i])&&(s=(o<3?a(s):o>3?a(e,t,s):a(e,t))||s);return o>3&&s&&Object.defineProperty(e,t,s),s};import{css as R,LitElement as C}from"lit";import{property as p,state as S}from"lit/decorators.js";import{subscribeToRootEvent as u}from"./root-event-subscription.js";import{traverseToClosest as b}from"./utilities.js";import{parseCssColor as w,serializeOklch as x,gamutMapToSRGB as P}from"./color-engine.js";import{computeVariants as v}from"../root/helpers/compute-variants.js";import{computeSemanticProperties as m}from"../root/helpers/compute-semantic-properties.js";import{lightnessRampProperties as E}from"../root/helpers/lightness-ramp-properties.js";import{ROLE_NAMES as V,mergeTheme as U,semanticToCSS as A}from"./theme.js";import{alignAttributeTextInheritance as I,focusRing as O}from"./style-fragments.js";import{syncNormalizedAttribute as D}from"./attribute-helpers.js";import{INTENT_VARIANTS as y,normalizeIntentVariant as z}from"./intent-values.js";const k=new WeakMap;class n extends C{constructor(){super(...arguments),this.seedColorBacker="oklch(0.7 0.125 216)",this.espRoot=null,this.contextBacker="",this.scopedTokenOriginalValues=new Map,this.warnedUnknownContexts=new Set,this.pendingInitialThemeRoot=null,this.rootEventSubscriptionsActive=!1,this.subscribedRoot=null,this.rootEventUnsubscribers=[],this.intentBacker="neutral",this.intentEmitsTokens=!0,this.warnedUnknownIntents=new Set,this.correlationId=globalThis.crypto?.randomUUID?.()??Math.random().toString(36),this.scheme="light",this.handleSeedColorChanged=e=>{this.syncRootFromDom(!1)&&(this.seedColor=e.seedColor,this.applyScopedColorTokens())},this.handleSchemeChanged=e=>{!this.syncRootFromDom(!1)||this.scheme===e.scheme||(this.scheme=e.scheme,this.applyScopedColorTokens())},this.handleThemeChanged=()=>{this.syncRootFromDom(!1)&&this.applyScopedColorTokens()},this.handleIconSpriteUrlChanged=()=>{this.syncRootFromDom(!1)&&this.requestUpdate()}}get seedColor(){return this.seedColorBacker}set seedColor(e){this.seedColorBacker=e}focusResolvedElementAfterUpdate(e,t){const r=()=>{const o=e();return o?(o.focus(t),!0):!1};r()||this.updateComplete.then(()=>{r()})}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 intent(){return this.intentBacker}set intent(e){const t=typeof e=="string"?e.trim():"";t!==""&&!y.includes(t)&&!this.warnedUnknownIntents.has(t)&&(this.warnedUnknownIntents.add(t),console.warn(`Espalier intent: "${t}" is not an intent; expected one of ${y.join(", ")}. Treating it as "neutral".`));const r=this.intentBacker,o=z(e);D(this,"intent",o),o!==r&&(this.intentBacker=o,this.requestUpdate("intent",r),this.applyTokensWhenRootReady())}get context(){return this.contextBacker}set context(e){const t=e??"";t!==this.contextBacker&&(this.contextBacker=t,this.applyTokensWhenRootReady(),this.refreshDescendantIntentDerivations())}refreshDescendantIntentDerivations(){const e=new Set,t=o=>{for(const s of Array.from(o.children))r(s)},r=o=>{if(!e.has(o)){if(e.add(o),o instanceof n&&o.applyTokensWhenRootReady(),o.shadowRoot&&t(o.shadowRoot),o instanceof HTMLSlotElement)for(const s of o.assignedElements({flatten:!0}))r(s);t(o)}};t(this),this.shadowRoot&&t(this.shadowRoot)}static flattenedParent(e){return e instanceof Element&&e.assignedSlot?e.assignedSlot:e instanceof ShadowRoot?e.host:e.parentNode}resolveAncestorZoneTheme(e){let t=n.flattenedParent(this);for(;t;){if(t instanceof Element&&t.localName==="esp-root")return null;if(t instanceof n){const r=t.contextBacker.trim();if(r){const o=this.resolveNamedContextTheme(e,r);if(o)return o}}t=n.flattenedParent(t)}return null}connectedCallback(){super.connectedCallback();const e=this.syncRootFromDom(!1);e&&this.subscribeToRootEvents(e)}disconnectedCallback(){super.disconnectedCallback(),this.unsubscribeFromRootEvents(),this.clearScopedTokens(),this.espRoot=null}firstUpdated(e){this.syncRootFromDom(!0),this.applyTokensWhenRootReady()}syncRootFromDom(e){const t=b(this,"esp-root");if(!t){if(this.espRoot&&this.clearScopedTokens(),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 r=t!==this.espRoot,s=t.scheme==="dark"?"dark":"light",a=this.scheme!==s,i=this.seedColor!==t.seedColor;return this.espRoot=t,r&&this.isConnected&&this.subscribeToRootEvents(t),(r||a||i)&&(this.scheme=s,this.seedColor=t.seedColor,this.applyTokensWhenRootReady()),r&&this.requestUpdate(),t}applyTokensWhenRootReady(){const e=this.espRoot;if(e&&(!e.hasUpdated||e.isUpdatePending)){this.applyTokensAfterInitialRootUpdate(e);return}this.applyScopedColorTokens()}applyTokensAfterInitialRootUpdate(e){if(this.pendingInitialThemeRoot===e)return;this.pendingInitialThemeRoot=e;const t=e.updateComplete;if(!t){this.pendingInitialThemeRoot=null,this.applyScopedColorTokens();return}t.then(()=>{this.pendingInitialThemeRoot===e&&(this.pendingInitialThemeRoot=null),!(!this.isConnected||this.espRoot!==e)&&(this.scheme=e.scheme==="dark"?"dark":"light",this.seedColor=e.seedColor,this.applyScopedColorTokens())})}subscribeToRootEvents(e){this.rootEventSubscriptionsActive&&this.subscribedRoot===e||(this.unsubscribeFromRootEvents(),this.subscribedRoot=e,this.rootEventUnsubscribers=[u(e,"seed-color-changed",this.handleSeedColorChanged),u(e,"scheme-changed",this.handleSchemeChanged),u(e,"theme-changed",this.handleThemeChanged),u(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 b(this,e)}applyScopedColorTokens(){if(!this.espRoot)return;const e=this.intentEmitsTokens?n.intentColorSources[this.intentBacker]:"";if(!e&&!this.context.trim()){this.clearScopedTokens();return}const t=this.espRoot.activeTheme;if(!t){this.clearScopedTokens();return}const r=this.resolveContextTheme(t),o=r.theme,s=w(o.seedColor);if(!s)return;const a=v(s,o),i={};if(r.applied&&(Object.assign(i,m(o,a)),Object.assign(i,E(o))),e){let c=o;r.applied||(c=this.resolveAncestorZoneTheme(t)??o);const l=c===o?a:v(s,c),T=m(c,l,{effectiveSource:(g,d)=>n.semanticActionTokens.has(g)?e:d});i["--esp-color-primary"]=x(P(l[e]));for(const g of n.semanticActionTokens){const d=A(g);i[d]=T[d]}}this.applyScopedTokenProperties(i)}resolveContextTheme(e){const t=this.context.trim();if(!t)return{applied:!1,theme:e};const r=this.resolveNamedContextTheme(e,t);return r?{applied:!0,theme:r}:(this.warnedUnknownContexts.has(t)||(this.warnedUnknownContexts.add(t),console.warn(`Espalier context: "${t}" is not defined by the active theme; inheriting root tokens.`)),{applied:!1,theme:e})}resolveNamedContextTheme(e,t){const r=e.contexts&&Object.prototype.hasOwnProperty.call(e.contexts,t)?e.contexts[t]:void 0;if(!r)return null;let o=k.get(e);const s=o?.get(t);if(s)return s;const a={};for(const c of V){const l=r[c];l!==void 0&&(a[c]=l)}const i=U(e,{lightness:r.lightness,roles:a});return o||(o=new Map,k.set(e,o)),o.set(t,i),i}applyScopedTokenProperties(e){for(const t of this.scopedTokenOriginalValues.keys())t in e||this.restoreScopedTokenProperty(t);for(const[t,r]of Object.entries(e))this.setScopedTokenProperty(t,r)}setScopedTokenProperty(e,t){const r=this.scopedTokenOriginalValues.get(e);if(r){const o=this.style.getPropertyValue(e),s=this.style.getPropertyPriority(e);(o!==r.generatedValue||s!==r.generatedPriority)&&(r.originalValue=o.length?o:null,r.originalPriority=s),r.generatedValue=t,r.generatedPriority=""}else{const o=this.style.getPropertyValue(e);this.scopedTokenOriginalValues.set(e,{generatedPriority:"",generatedValue:t,originalPriority:this.style.getPropertyPriority(e),originalValue:o.length?o:null})}this.style.setProperty(e,t)}restoreScopedTokenProperty(e){const t=this.scopedTokenOriginalValues.get(e);if(!t)return;const r=this.style.getPropertyValue(e),o=this.style.getPropertyPriority(e);(r!==t.generatedValue||o!==t.generatedPriority)&&(t.originalValue=r.length?r:null,t.originalPriority=o),t.originalValue===null?this.style.removeProperty(e):this.style.setProperty(e,t.originalValue,t.originalPriority),this.scopedTokenOriginalValues.delete(e)}clearScopedTokens(){for(const e of[...this.scopedTokenOriginalValues.keys()])this.restoreScopedTokenProperty(e)}}n.intentColorSources={danger:"danger",info:"info",neutral:"",success:"success",warning:"warning"},n.semanticActionTokens=new Set(["actionBackground","actionText"]),n.styles=[O(".esp-field:focus-within","--esp-field-focus-shadow"),I,R`
|
|
2
2
|
:host {
|
|
3
3
|
|
|
4
4
|
--_esp-field-resolved-hover-bg: var(
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import{css as o,unsafeCSS as e}from"lit";const
|
|
1
|
+
import{css as o,unsafeCSS as e}from"lit";const a=o`
|
|
2
2
|
:host([align]) {
|
|
3
3
|
text-align: inherit;
|
|
4
4
|
}
|
|
5
|
-
`,
|
|
5
|
+
`,l=o`
|
|
6
6
|
.sr-only {
|
|
7
7
|
position: absolute;
|
|
8
8
|
width: 1px;
|
|
@@ -50,8 +50,8 @@ import{css as o,unsafeCSS as e}from"lit";const l=o`
|
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
.intent-info {
|
|
53
|
-
--_esp-intent-background: var(--esp-color-
|
|
54
|
-
--_esp-intent-border-color: oklch(from var(--esp-color-
|
|
55
|
-
--_esp-intent-color: var(--esp-color-
|
|
53
|
+
--_esp-intent-background: oklch(from var(--esp-color-info) var(--esp-l-raised-2) c h);
|
|
54
|
+
--_esp-intent-border-color: oklch(from var(--esp-color-info) var(--esp-l-border) c h);
|
|
55
|
+
--_esp-intent-color: oklch(from var(--esp-color-info) var(--esp-l-text) c h);
|
|
56
56
|
}
|
|
57
|
-
`;export{
|
|
57
|
+
`;export{a as alignAttributeTextInheritance,i as disabledControl,p as focusRing,d as intentSurfaceTokens,l as srOnly};
|
package/dist/shared/theme.d.ts
CHANGED
|
@@ -36,21 +36,35 @@ export type LightnessKey = "surface" | "raised1" | "raised2" | "raised3" | "rais
|
|
|
36
36
|
/** Lightness values (0–1) for every ramp position. */
|
|
37
37
|
export type LightnessMap = Record<LightnessKey, number>;
|
|
38
38
|
/**
|
|
39
|
-
* A geometric color-theory variant **or** a fixed
|
|
39
|
+
* A geometric color-theory variant **or** a fixed status family.
|
|
40
40
|
*
|
|
41
|
-
* Geometric variants are derived by rotating the seed hue;
|
|
42
|
-
*
|
|
43
|
-
*
|
|
41
|
+
* Geometric variants are derived by rotating the seed hue; the status
|
|
42
|
+
* families (`danger`, `success`, `warning`, `info`) use fixed hue
|
|
43
|
+
* angles from `semanticHues` — or a theme's `intents` override, which
|
|
44
|
+
* retunes a family with a declared absolute color (ESP0172).
|
|
44
45
|
*/
|
|
45
|
-
export type ColorSource = "primary" | "analogous-left" | "analogous-right" | "complementary" | "split-complementary-left" | "split-complementary-right" | "triadic-left" | "triadic-right" | "danger" | "success" | "warning";
|
|
46
|
+
export type ColorSource = "primary" | "analogous-left" | "analogous-right" | "complementary" | "split-complementary-left" | "split-complementary-right" | "triadic-left" | "triadic-right" | "danger" | "success" | "warning" | "info";
|
|
46
47
|
/**
|
|
47
|
-
* Non-primary color sources — the
|
|
48
|
+
* Non-primary color sources — the eleven variants that can carry
|
|
48
49
|
* independent chroma overrides.
|
|
49
50
|
*
|
|
50
51
|
* Primary is excluded because its chroma is always the seed
|
|
51
52
|
* color's chroma.
|
|
52
53
|
*/
|
|
53
54
|
export type VariantColorSource = Exclude<ColorSource, "primary">;
|
|
55
|
+
/**
|
|
56
|
+
* The fixed-meaning status families (ADR-004): the colors
|
|
57
|
+
* `intent="danger|success|warning|info"` and the same-named mapping
|
|
58
|
+
* sources resolve to. A theme may retune each with `intents`.
|
|
59
|
+
*/
|
|
60
|
+
export type StatusColorSource = "danger" | "success" | "warning" | "info";
|
|
61
|
+
/**
|
|
62
|
+
* Status-family color overrides, by family (ESP0172). Values are an
|
|
63
|
+
* `anchor:<name>[.<slot>]` reference or a supported color form
|
|
64
|
+
* (`#rrggbb`, `#rgb`, `rgb()`, `hsl()`, `oklch()`); see
|
|
65
|
+
* {@link EspalierTheme.intents}.
|
|
66
|
+
*/
|
|
67
|
+
export type ThemeIntents = Partial<Record<StatusColorSource, string>>;
|
|
54
68
|
/**
|
|
55
69
|
* The object form of an anchor: a required base `color` plus named
|
|
56
70
|
* sub-slots — per-family variants the way designers already specify
|
|
@@ -175,9 +189,11 @@ export type SemanticMappings = Record<SemanticColorName, SemanticMapping>;
|
|
|
175
189
|
* automatically (see {@link ROLE_PAIRED_INK})
|
|
176
190
|
* - `structure` — borders and shadows
|
|
177
191
|
*
|
|
178
|
-
* `status` is deliberately absent: the
|
|
179
|
-
*
|
|
180
|
-
*
|
|
192
|
+
* `status` is deliberately absent as a role: the four status families
|
|
193
|
+
* (`danger`, `success`, `warning`, `info`) carry reserved *meanings*
|
|
194
|
+
* that no role may reassign (ADR-004, as amended). Their *colors* are
|
|
195
|
+
* a brand decision — retune a family with the theme's `intents` field
|
|
196
|
+
* and every derived token follows.
|
|
181
197
|
*/
|
|
182
198
|
export type RoleName = "canvas" | "ink" | "accent" | "action" | "structure";
|
|
183
199
|
/**
|
|
@@ -190,7 +206,7 @@ export type RoleName = "canvas" | "ink" | "accent" | "action" | "structure";
|
|
|
190
206
|
export type RoleSlotName = {
|
|
191
207
|
canvas: never;
|
|
192
208
|
ink: "heading";
|
|
193
|
-
accent: "text";
|
|
209
|
+
accent: "text" | "hover";
|
|
194
210
|
action: "ink";
|
|
195
211
|
structure: never;
|
|
196
212
|
};
|
|
@@ -232,7 +248,10 @@ export declare const ROLE_NAMES: readonly RoleName[];
|
|
|
232
248
|
* The `accent` role has no body-text slot on purpose. "Rose is
|
|
233
249
|
* decorative only" is a structural guarantee here, not a comment: text
|
|
234
250
|
* that must come from the accent family comes through `accent.text`,
|
|
235
|
-
* the deepened variant a designer picked for legibility.
|
|
251
|
+
* the deepened variant a designer picked for legibility. `accent.hover`
|
|
252
|
+
* lets a hover change *family*, not just lightness — "plum link, rose
|
|
253
|
+
* hover" is an ordinary brand rule (ESP0172); absent, `linkHover` keeps
|
|
254
|
+
* following `accent.text` exactly as before.
|
|
236
255
|
*/
|
|
237
256
|
export declare const ROLE_TOKEN_PLAN: Readonly<Record<RoleName, Readonly<Record<string, ReadonlyArray<[SemanticColorName, LightnessKey]>>>>>;
|
|
238
257
|
/**
|
|
@@ -356,7 +375,7 @@ export interface EspalierTheme {
|
|
|
356
375
|
/** Triadic offset from seed (default 120). */
|
|
357
376
|
triadic: number;
|
|
358
377
|
};
|
|
359
|
-
/** Fixed hue angles for danger / success / warning
|
|
378
|
+
/** Fixed hue angles for the danger / success / warning / info families. */
|
|
360
379
|
semanticHues: {
|
|
361
380
|
/** Danger hue angle (default 27, red-orange). */
|
|
362
381
|
danger: number;
|
|
@@ -364,7 +383,46 @@ export interface EspalierTheme {
|
|
|
364
383
|
success: number;
|
|
365
384
|
/** Warning hue angle (default 90, yellow-green). */
|
|
366
385
|
warning: number;
|
|
386
|
+
/** Info hue angle (default 244, blue). */
|
|
387
|
+
info: number;
|
|
367
388
|
};
|
|
389
|
+
/**
|
|
390
|
+
* Status-family color overrides, by family (ESP0172).
|
|
391
|
+
*
|
|
392
|
+
* Each entry retunes one of the fixed status families — the colors
|
|
393
|
+
* `intent="danger|success|warning|info"` and the same-named mapping
|
|
394
|
+
* sources resolve to — with a declared color: an
|
|
395
|
+
* `anchor:<name>[.<slot>]` reference or a supported color form —
|
|
396
|
+
* `#rrggbb`, `#rgb`, `rgb()`, `hsl()`, or `oklch()`. CSS keywords
|
|
397
|
+
* such as `red` are not parsed.
|
|
398
|
+
*
|
|
399
|
+
* An override is **absolute**, like an anchor: it carries its own
|
|
400
|
+
* lightness, chroma, and hue, and `semanticHues` / `variantChroma`
|
|
401
|
+
* are ignored for that family. Overrides retune a family; they do
|
|
402
|
+
* not reassign its meaning (ADR-004): give `danger` your brand's
|
|
403
|
+
* red, but never point one family at another — a family name as a
|
|
404
|
+
* value (`intents.success: "danger"`) is rejected by validation; a
|
|
405
|
+
* color choice that creates a rendered collision is flagged by the
|
|
406
|
+
* distance warning, while a merely unusual — but separated — color
|
|
407
|
+
* passes silently. `validateTheme` warns when two
|
|
408
|
+
* status families — or a family and the action color — become hard
|
|
409
|
+
* to distinguish as rendered on controls, and its advice is
|
|
410
|
+
* counterfactual-tested per pair: it recommends retuning, widening
|
|
411
|
+
* the chroma band, or moving the lightness stop only when that
|
|
412
|
+
* change can actually separate the pair, and says "then retune"
|
|
413
|
+
* when a band or stop change merely makes a retune possible rather
|
|
414
|
+
* than separating the pair on its own. The built-in warning is
|
|
415
|
+
* normal-vision-only; status meanings need redundant cues (icons,
|
|
416
|
+
* labels) regardless, though lightness and chroma separation chosen
|
|
417
|
+
* here can still genuinely help color-vision-deficient users — see
|
|
418
|
+
* ADR-004's amendment and the data-color guidance.
|
|
419
|
+
*
|
|
420
|
+
* @example
|
|
421
|
+
* ```jsonc
|
|
422
|
+
* "intents": { "info": "anchor:sky", "danger": "#700007" }
|
|
423
|
+
* ```
|
|
424
|
+
*/
|
|
425
|
+
intents: ThemeIntents;
|
|
368
426
|
/**
|
|
369
427
|
* Per-variant chroma overrides (OKLCH chroma, 0–0.4).
|
|
370
428
|
*
|
|
@@ -489,10 +547,12 @@ export declare const TOKEN_PAIRINGS: Readonly<Record<"actionText", TokenPairing>
|
|
|
489
547
|
export declare const SEMANTIC_COLOR_NAMES: readonly SemanticColorName[];
|
|
490
548
|
/** Valid color-source identifiers for {@link SemanticMapping.source}. */
|
|
491
549
|
export declare const COLOR_SOURCES: readonly ColorSource[];
|
|
550
|
+
/** The four fixed status families, matching {@link StatusColorSource}. */
|
|
551
|
+
export declare const STATUS_COLOR_SOURCES: readonly StatusColorSource[];
|
|
492
552
|
/**
|
|
493
553
|
* Non-primary color sources that support independent chroma overrides.
|
|
494
554
|
*
|
|
495
|
-
* Matches the
|
|
555
|
+
* Matches the eleven entries in {@link VariantColorSource}.
|
|
496
556
|
*/
|
|
497
557
|
export declare const VARIANT_COLOR_SOURCES: readonly VariantColorSource[];
|
|
498
558
|
/** Valid keys for the lightness ramp. */
|
|
@@ -587,13 +647,26 @@ export declare function encodeTheme(partial: PartialTheme): string;
|
|
|
587
647
|
* @returns A new fully-resolved {@link EspalierTheme}.
|
|
588
648
|
*/
|
|
589
649
|
export declare function mergeTheme(defaults: EspalierTheme, overrides: PartialTheme): EspalierTheme;
|
|
650
|
+
/**
|
|
651
|
+
* Validate a single encoded theme partial.
|
|
652
|
+
*
|
|
653
|
+
* Structural grammar aside, the advisory checks (the status-collision
|
|
654
|
+
* warning and chroma-band provenance) resolve the partial against
|
|
655
|
+
* {@link DEFAULT_LIGHT_THEME}. A partial written for the dark side of a
|
|
656
|
+
* pair should be validated through {@link validateThemePair}, which
|
|
657
|
+
* audits it against the dark defaults instead.
|
|
658
|
+
*/
|
|
590
659
|
export declare function validateTheme(base64: string): ThemeValidationResult;
|
|
591
660
|
/**
|
|
592
661
|
* Validate the light and dark partials that form one scheme-paired theme.
|
|
593
662
|
*
|
|
594
|
-
* Each
|
|
595
|
-
*
|
|
596
|
-
*
|
|
663
|
+
* Each side runs the same validation as {@link validateTheme}, with one
|
|
664
|
+
* scheme-aware difference: the dark partial's advisory checks resolve
|
|
665
|
+
* against {@link DEFAULT_DARK_THEME}, so a collision that only appears
|
|
666
|
+
* through the dark ramp is caught. Once both sides are structurally
|
|
667
|
+
* valid, their context-name sets must match exactly so a stable
|
|
668
|
+
* `context` attribute cannot silently change meaning when the scheme
|
|
669
|
+
* changes.
|
|
597
670
|
*/
|
|
598
671
|
export declare function validateThemePair(lightBase64: string, darkBase64: string): ThemeValidationResult;
|
|
599
672
|
/**
|
|
@@ -601,7 +674,7 @@ export declare function validateThemePair(lightBase64: string, darkBase64: strin
|
|
|
601
674
|
* and therefore need key-by-key merging instead of wholesale
|
|
602
675
|
* replacement when combining two {@link PartialTheme} objects.
|
|
603
676
|
*/
|
|
604
|
-
export declare const NESTED_THEME_KEYS: readonly ["anchors", "angles", "contexts", "dataPalette", "dataRamps", "roles", "chroma", "lightness", "semanticHues", "semanticMappings", "variantChroma"];
|
|
677
|
+
export declare const NESTED_THEME_KEYS: readonly ["anchors", "angles", "contexts", "dataPalette", "dataRamps", "intents", "roles", "chroma", "lightness", "semanticHues", "semanticMappings", "variantChroma"];
|
|
605
678
|
/**
|
|
606
679
|
* Deep-merge two {@link PartialTheme} objects.
|
|
607
680
|
*
|
package/dist/shared/theme.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{ACCEPTED_COLOR_FORMS as I,apcaContrast as pe,deriveSemantic as me,parseCssColor as O,parseOklch as ge,serializeOklch as de}from"./color-engine.js";import{computeVariants as he,parseAnchorSource as ye,resolveAnchorColor as be,resolveMappingSource as $e}from"./variant-engine.js";import{auditDataPalette as xe,DATA_SERIES_KEYS as P,DEFAULT_DATA_PALETTE as F,DEFAULT_DATA_RAMP_STEPS as ke,MAX_DATA_RAMP_STEPS as W,MIN_DATA_RAMP_LIGHTNESS_STEP as Y,MIN_DATA_RAMP_STEPS as j}from"./data-colors.js";const A=/^[a-z][a-z0-9-]*$/;function X(e){return ye(e)}function Se(e,t){return be(e,t)}function Ae(e,t){const r=X(e);if(r){const s=Se(t,r);return s&&O(s)?s:null}return O(e)?e:null}const H=["canvas","ink","accent","action","structure"],Z={canvas:{color:[["background","surface"],["layer1","raised1"],["layer2","raised2"],["layer3","raised3"],["layer4","raised4"]]},ink:{color:[["text","text"],["inputSelection","text"]],heading:[["headings","muted"],["headingsHover","ink"]]},accent:{color:[["linkHoverBg","raised2"],["inputSelectionBg","raised2"],["inputCaret","ink"]],text:[["link","accent"],["linkHover","text"]]},action:{color:[["actionBackground","muted"]],ink:[["actionText","surface"]]},structure:{color:[["border","border"],["shadow","shadow"]]}},Re=new Set(["action.color"]),Oe={canvas:"background",ink:"text",accent:"link",action:"actionBackground",structure:"border"},Ce={"action.ink":{role:"canvas",slot:"color"}},ve=.45;function Q(e,t){const r=te.actionText,s=[...R].sort((p,y)=>e[p]-e[y]||R.indexOf(p)-R.indexOf(y)),a=t?s.filter(p=>t(p)>=r.targetLc):s,u=a.length>0?a:s;let l,m=1/0;for(const p of u){const y=Math.abs(e[p]-ve);y<m&&(m=y,l=p)}return l??"muted"}function Me(e,t){const r=t[e]>.5;let s=R[0];for(const a of R)(r?t[a]<t[s]:t[a]>t[s])&&(s=a);return s}function L(e,t){if(e===void 0)return;if(typeof e=="string")return t==="color"?e:void 0;const r=e[t];return typeof r=="string"?r:void 0}function ee(e,t,r,s={}){const a={},u={};for(const[l,m]of Object.entries(s.explicitMappings??{}))m!==void 0&&(u[l]=m.lightness);for(const l of H){const m=e[l];if(m!==void 0)for(const[p,y]of Object.entries(Z[l])){const b=Ce[`${l}.${p}`];let h=L(m,p),n=!1;if(h===void 0&&(b&&(h=L(e[b.role],b.slot),h??=r[Oe[b.role]]?.source,n=h!==void 0),h??=L(m,"color")),h!==void 0)for(const[o,c]of y){let i=c;if(Re.has(`${l}.${p}`))i=Q(t,s.actionSurfaceContrast?f=>s.actionSurfaceContrast(h,f):void 0);else if(n&&b){const f=te[o],d=(f&&u[f.bg])??Q(t,s.actionSurfaceContrast?k=>s.actionSurfaceContrast(L(m,"color"),k):void 0);i=Me(d,t)}a[o]={source:h,lightness:i}}}}return a}const te={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}},z=["background","layer1","layer2","layer3","layer4","actionBackground","actionText","border","shadow","text","dangerText","headings","headingsHover","link","linkHover","linkHoverBg","inputCaret","inputSelection","inputSelectionBg"],K=["primary","analogous-left","analogous-right","complementary","split-complementary-left","split-complementary-right","triadic-left","triadic-right","danger","success","warning"],Te=["analogous-left","analogous-right","complementary","split-complementary-left","split-complementary-right","triadic-left","triadic-right","danger","success","warning"],R=["surface","raised1","raised2","raised3","raised4","accent","muted","text","border","ink","shadow"],Ee={surface:.99,raised1:.97,raised2:.9,raised3:.8,raised4:.72,accent:.5,muted:.45,text:.35,border:.3,ink:.25,shadow:.2},Be={surface:.15,raised1:.2,raised2:.3,raised3:.4,raised4:.36,accent:.6,muted:.75,text:.85,border:.7,ink:.95,shadow:.6},U={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"}},B=.4;function G(){const e={};for(const t of z)e[t]={min:0,max:B};return e}const ne={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:G(),semanticMappings:{...U},anchors:{},roles:{},contexts:{},dataPalette:{...F},dataRamps:{}},oe={...ne,chroma:G(),semanticMappings:{...U},anchors:{},roles:{},contexts:{},dataPalette:{...F},dataRamps:{},lightness:{...Ee}},we={...ne,chroma:G(),semanticMappings:{...U},anchors:{},roles:{},contexts:{},dataPalette:{...F},dataRamps:{},lightness:{...Be}},D=new WeakMap;D.set(oe,new Set),D.set(we,new Set);const se=new Set(["__proto__","constructor","prototype"]);function g(e){return!se.has(e)}function _e(e,t){return se.has(e)?void 0:t}function Ve(e){return`--esp-color-${e.replace(/([A-Z])/g,"-$1").replace(/(\d)/g,"-$1").toLowerCase()}`}function Ie(e){try{const t=atob(e),r=JSON.parse(t,_e);return typeof r!="object"||r===null||Array.isArray(r)?null:r}catch{return null}}function V(e){return btoa(JSON.stringify(e))}function N(e){if(ge(e))return e;const t=O(e);return t?de(t):e}function re(e,t){const r={};for(const[s,a]of Object.entries(e))g(s)&&(r[s]=a);if(!t)return r;for(const[s,a]of Object.entries(t)){if(a===void 0||!g(s))continue;const u=r[s];if(u!==void 0&&typeof a=="object"&&a!==null){const l={};if(typeof u=="string")l.color=u;else for(const[m,p]of Object.entries(u))g(m)&&(l[m]=p);for(const[m,p]of Object.entries(a))p!==void 0&&g(m)&&(l[m]=p);r[s]=l;continue}r[s]=a}return r}function ae(e){if(typeof e!="object"||e===null||Array.isArray(e))return null;const t=e,r={};for(const s of H){const a=t[s];a!==void 0&&(r[s]=a)}if(typeof t.lightness=="object"&&t.lightness!==null&&!Array.isArray(t.lightness)){const s={};for(const a of R){const u=t.lightness[a];u!==void 0&&(s[a]=u)}r.lightness=s}return r}function Pe(e,t){const r={};for(const[s,a]of Object.entries(e)){if(!g(s)||!A.test(s))continue;const u=ae(a);u&&(r[s]=u)}if(!t)return r;for(const[s,a]of Object.entries(t)){if(!g(s)||!A.test(s)||a===void 0)continue;const u=ae(a);if(!u)continue;const l=r[s];r[s]={...l??{},...u,...l?.lightness||u.lightness?{lightness:{...l?.lightness,...u.lightness}}:{}}}return r}function v(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function M(e){const t={};for(const[r,s]of Object.entries(e))s!==void 0&&g(r)&&(t[r]=s);return t}function ie(e){if(!v(e))return e;const t=M(e);return v(e.lightness)&&(t.lightness=M(e.lightness)),t}function He(e,t){const r={};for(const[s,a]of Object.entries(e))g(s)&&(r[s]=ie(a));if(!t)return r;for(const[s,a]of Object.entries(t)){if(!g(s)||a===void 0)continue;const u=r[s];if(!v(u)||!v(a)){r[s]=ie(a);continue}const l={...M(u),...M(a)};v(u.lightness)&&v(a.lightness)?l.lightness={...M(u.lightness),...M(a.lightness)}:v(a.lightness)&&(l.lightness=M(a.lightness)),r[s]=l}return r}function Le(e){const t={};for(const[r,s]of Object.entries(e)){if(!g(r))continue;if(typeof s=="string"){t[r]=N(s);continue}const a={};for(const[u,l]of Object.entries(s))g(u)&&(a[u]=typeof l=="string"?N(l):l);t[r]=a}return t}function w(e){return typeof e!="string"?"":e.startsWith("anchor:")?e:N(e)}function De(e){const t={};for(const r of P)t[r]=w(e[r]);return t}function ce(e,t){const r={};for(const[s,a]of Object.entries(e))g(s)&&A.test(s)&&a&&typeof a=="object"&&!Array.isArray(a)&&(r[s]={...a});if(!t)return r;for(const[s,a]of Object.entries(t)){if(!g(s)||!A.test(s)||!a||typeof a!="object"||Array.isArray(a))continue;const u=r[s],l=u!==void 0&&a.type!==void 0&&a.type!==u.type;r[s]={...l?{}:u??{},...a}}return r}function Ne(e){const t={};for(const[r,s]of Object.entries(e))if(g(r)){if(s.type==="sequential"&&typeof s.source=="string"){t[r]={...s,source:w(s.source)};continue}if(s.type==="diverging"&&typeof s.start=="string"&&typeof s.end=="string"){t[r]={...s,start:w(s.start),end:w(s.end),...typeof s.neutral=="string"?{neutral:w(s.neutral)}:{}};continue}t[r]={...s}}return t}function ue(e){const t=O(e.seedColor);if(!t)return;const r=he(t,e);return(s,a)=>{const u=$e(s,r,e.anchors)??r.primary,l=e.chroma.actionBackground,m=me(u,e.lightness[a],l.min,l.max),p={l:m.l>.5?0:1,c:0,h:0};return Math.abs(pe(p,m))}}function Fe(e){const t=D.get(e);if(t)return new Set(t);const r=new Set,s=ee(e.roles,e.lightness,e.semanticMappings,{actionSurfaceContrast:ue(e)});for(const[a,u]of Object.entries(s)){const l=e.semanticMappings[a];(l.source!==u.source||l.lightness!==u.lightness)&&r.add(a)}return r}function We(e,t){const r={...e.roles,...t.roles},s=Pe(e.contexts,t.contexts),a={...e.lightness,...t.lightness},u=Le(re(e.anchors,t.anchors)),l=typeof t.seedColor=="string"?N(t.seedColor):e.seedColor,m=t.semanticMappings,p={...e.angles,...t.angles},y={...e.semanticHues,...t.semanticHues},b={...e.variantChroma,...t.variantChroma},h=_(e.chroma,t.chroma),n=De(_(e.dataPalette,t.dataPalette)),o=Ne(ce(e.dataRamps,t.dataRamps)),c=Fe(e),i=new Set(c),f={};for(const x of c)f[x]=e.semanticMappings[x];for(const[x,T]of Object.entries(m??{}))T!==void 0&&(i.add(x),f[x]=T);const d=_(e.semanticMappings,m),k=ue({angles:p,anchors:u,chroma:h,lightness:a,seedColor:l,semanticHues:y,variantChroma:b}),S=ee(r,a,d,{explicitMappings:f,actionSurfaceContrast:k}),E={};for(const[x,T]of Object.entries(S))i.has(x)||(E[x]=T);const C=_(_(e.semanticMappings,E),m),$={...e,seedColor:l,fontBody:t.fontBody??e.fontBody,fontHeadings:t.fontHeadings??e.fontHeadings,fontBrand:t.fontBrand??e.fontBrand,fontMonospace:t.fontMonospace??e.fontMonospace,fontWeightBody:String(t.fontWeightBody??e.fontWeightBody),fontWeightHeadings:String(t.fontWeightHeadings??e.fontWeightHeadings),fontWeightBrand:String(t.fontWeightBrand??e.fontWeightBrand),fontWeightMonospace:String(t.fontWeightMonospace??e.fontWeightMonospace),stylesheets:t.stylesheets??[...e.stylesheets],rootFontSize:t.rootFontSize??e.rootFontSize,typeRatio:t.typeRatio??e.typeRatio,spaceRatio:t.spaceRatio??e.spaceRatio,borderRadius:t.borderRadius??e.borderRadius,viewportMin:t.viewportMin??e.viewportMin,viewportMax:t.viewportMax??e.viewportMax,angles:p,semanticHues:y,variantChroma:b,lightness:a,chroma:h,semanticMappings:C,anchors:u,roles:r,contexts:s,dataPalette:n,dataRamps:o};return t.pageBackgroundImage!==void 0&&($.pageBackgroundImage=t.pageBackgroundImage),t.pageBackgroundImageOpacity!==void 0&&($.pageBackgroundImageOpacity=t.pageBackgroundImageOpacity),t.boxBackgroundImage!==void 0&&($.boxBackgroundImage=t.boxBackgroundImage),t.boxBackgroundImageOpacity!==void 0&&($.boxBackgroundImageOpacity=t.boxBackgroundImageOpacity),t.vellumOpacity!==void 0&&($.vellumOpacity=t.vellumOpacity),t.vellumBackgroundImage!==void 0&&($.vellumBackgroundImage=t.vellumBackgroundImage),t.vellumBackgroundImageOpacity!==void 0&&($.vellumBackgroundImageOpacity=t.vellumBackgroundImageOpacity),D.set($,new Set(i)),$}function _(e,t){if(!t)return{...e};const r={...e};for(const s of Object.keys(t)){const a=t[s];a!==void 0&&(r[s]=a)}return r}function J(e){let t;try{t=atob(e)}catch{return{error:"Failed to decode Base64 string."}}let r;try{r=JSON.parse(t)}catch{return{error:"Decoded string is not valid JSON."}}return typeof r!="object"||r===null||Array.isArray(r)?{error:"Theme must be a JSON object."}:{value:r}}function Je(e){const t=J(e);return t.error!==void 0?{valid:!1,errors:[t.error],warnings:[]}:q(t.value)}function q(e){const t=[],r=[];"seedColor"in e&&(typeof e.seedColor!="string"?t.push("seedColor must be a string."):O(e.seedColor)||t.push(`seedColor is not a valid CSS color: "${e.seedColor}". Accepted forms: ${I}.`));for(const n of["fontBody","fontHeadings","fontBrand","fontMonospace"])n in e&&typeof e[n]!="string"&&t.push(`${n} must be a string.`);const s=["normal","bold","lighter","bolder"],a=["inherit","initial","unset","revert","revert-layer"];for(const n of["fontWeightBody","fontWeightHeadings","fontWeightBrand","fontWeightMonospace"])if(n in e){const o=e[n];if(typeof o=="number")(o<1||o>1e3)&&t.push(`${n} numeric value must be 1\u20131000 (got ${o}).`);else if(typeof o=="string"){const c=s.includes(o)||a.includes(o);if(/^\d+$/.test(o)){const f=Number(o);(f<1||f>1e3)&&t.push(`${n} numeric value must be 1\u20131000 (got "${o}").`)}else c||r.push(`${n} = "${o}" is not a standard font-weight value.`)}else t.push(`${n} must be a string or number.`)}"stylesheets"in e&&(Array.isArray(e.stylesheets)?e.stylesheets.some(n=>typeof n!="string")&&t.push("Every entry in stylesheets must be a string."):t.push("stylesheets must be an array of strings."));const u=[["rootFontSize",1,100],["borderRadius",0,10],["viewportMin",100,1e4],["viewportMax",200,1e4]];for(const[n,o,c]of u)if(n in e)if(typeof e[n]!="number"||!isFinite(e[n]))t.push(`${n} must be a finite number.`);else{const i=e[n];o!==void 0&&i<o&&t.push(`${n} must be \u2265 ${o} (got ${i}).`),c!==void 0&&i>c&&r.push(`${n} = ${i} is unusually high (max ${c}).`)}for(const n of["typeRatio","spaceRatio"])if(n in e)if(typeof e[n]!="number"||!isFinite(e[n]))t.push(`${n} must be a finite number.`);else{const o=e[n];o<=1&&t.push(`${n} must be > 1 (got ${o}).`);const c=n==="typeRatio"?1.3:2;o>c&&r.push(`${n} = ${o} is very high (max ${c}); scales may be extreme.`)}if("viewportMin"in e&&"viewportMax"in e){const n=e.viewportMin,o=e.viewportMax;typeof n=="number"&&typeof o=="number"&&n>=o&&t.push(`viewportMin (${n}) must be less than viewportMax (${o}).`)}if("angles"in e)if(typeof e.angles!="object"||e.angles===null)t.push("angles must be an object.");else{const n=e.angles;for(const o of["analogous","complementary","splitComplementary","triadic"])if(o in n)if(typeof n[o]!="number"||!isFinite(n[o]))t.push(`angles.${o} must be a finite number.`);else{const c=n[o];(c<0||c>360)&&r.push(`angles.${o} = ${c} is outside 0\u2013360.`)}}if("semanticHues"in e)if(typeof e.semanticHues!="object"||e.semanticHues===null)t.push("semanticHues must be an object.");else{const n=e.semanticHues;for(const o of["danger","success","warning"])if(o in n)if(typeof n[o]!="number"||!isFinite(n[o]))t.push(`semanticHues.${o} must be a finite number.`);else{const c=n[o];(c<0||c>360)&&r.push(`semanticHues.${o} = ${c} is outside 0\u2013360.`)}}if("variantChroma"in e)if(typeof e.variantChroma!="object"||e.variantChroma===null)t.push("variantChroma must be an object.");else{const n=e.variantChroma;for(const o of Te)if(o in n)if(typeof n[o]!="number"||!isFinite(n[o]))t.push(`variantChroma["${o}"] must be a finite number.`);else{const c=n[o];c<0&&t.push(`variantChroma["${o}"] must be \u2265 0 (got ${c}).`),c>B&&r.push(`variantChroma["${o}"] = ${c} exceeds ${B}.`)}}function l(n,o){if(typeof n!="object"||n===null||Array.isArray(n)){t.push(`${o} must be an object.`);return}const c=n;for(const i of R)if(i in c)if(typeof c[i]!="number"||!isFinite(c[i]))t.push(`${o}.${i} must be a finite number.`);else{const f=c[i];(f<0||f>1)&&t.push(`${o}.${i} must be 0\u20131 (got ${f}).`)}}if("lightness"in e&&l(e.lightness,"lightness"),"chroma"in e)if(typeof e.chroma!="object"||e.chroma===null)t.push("chroma must be an object.");else{const n=e.chroma;for(const o of z)if(o in n){const c=n[o];if(typeof c!="object"||c===null){t.push(`chroma.${o} must be { min, max }.`);continue}const i=c;(typeof i.min!="number"||i.min<0)&&t.push(`chroma.${o}.min must be \u2265 0.`),(typeof i.max!="number"||i.max<0||i.max>B)&&t.push(`chroma.${o}.max must be 0\u2013${B}.`),typeof i.min=="number"&&typeof i.max=="number"&&i.min>i.max&&t.push(`chroma.${o}.min (${i.min}) must be \u2264 max (${i.max}).`)}}if("anchors"in e)if(typeof e.anchors!="object"||e.anchors===null||Array.isArray(e.anchors))t.push("anchors must be an object of named colors.");else for(const[n,o]of Object.entries(e.anchors))if(g(n)?A.test(n)||t.push(`anchors: "${n}" is not a valid anchor name; use a lowercase slug (letters, digits, hyphens).`):t.push(`anchors: "${n}" is a reserved JavaScript property name and cannot be an anchor name; rename it.`),K.includes(n)&&t.push(`anchors: "${n}" collides with a reserved color source name.`),typeof o=="string")O(o)||t.push(`anchors.${n} is not a valid CSS color: "${o}". Accepted forms: ${I}.`);else if(typeof o=="object"&&o!==null&&!Array.isArray(o)){const c=o;typeof c.color!="string"&&t.push(`anchors.${n} must declare its base "color".`);for(const[i,f]of Object.entries(c))g(i)?i!=="color"&&!A.test(i)&&t.push(`anchors.${n}: "${i}" is not a valid slot name; use a lowercase slug.`):t.push(`anchors.${n}: "${i}" is a reserved JavaScript property name and cannot be a slot name; rename it.`),typeof f!="string"?t.push(`anchors.${n}.${i} must be a CSS color string.`):O(f)||t.push(`anchors.${n}.${i} is not a valid CSS color: "${f}". Accepted forms: ${I}.`)}else t.push(`anchors.${n} must be a color string or a { color, \u2026slots } object.`);const m=new Map;if("anchors"in e&&typeof e.anchors=="object"&&e.anchors!==null&&!Array.isArray(e.anchors))for(const[n,o]of Object.entries(e.anchors))m.set(n,o);function p(n,o){const c=X(n);if(!c){t.push(`${o} "${n}" is not valid anchor syntax; use anchor:<name> or anchor:<name>.<slot>.`);return}if(!m.has(c.name)){const i=[...m.keys()];t.push(`${o} references undeclared anchor "${c.name}". Declared anchors: ${i.length>0?i.join(", "):"(none)"}.`);return}if(c.slot!==void 0){const i=m.get(c.name);if(typeof(typeof i=="object"&&i!==null&&!Array.isArray(i)?i[c.slot]:void 0)!="string"){const d=typeof i=="object"&&i!==null?Object.keys(i).filter(k=>k!=="color"):[];t.push(`${o} references unknown slot "${c.slot}" on anchor "${c.name}". Declared slots: ${d.length>0?d.join(", "):"(none)"}.`)}}}function y(n,o){if(n.startsWith("anchor:")){p(n,o);return}K.includes(n)||t.push(`${o} must be one of: ${K.join(", ")}, or a declared anchor as anchor:<name> / anchor:<name>.<slot>.`)}function b(n,o){if(n.startsWith("anchor:")){p(n,o);return}O(n)||t.push(`${o} is not a valid CSS color: "${n}". Accepted forms: ${I}, or a declared anchor as anchor:<name> / anchor:<name>.<slot>.`)}if("dataPalette"in e)if(typeof e.dataPalette!="object"||e.dataPalette===null||Array.isArray(e.dataPalette))t.push("dataPalette must be an object with series1\u2013series8 color values.");else{const n=e.dataPalette;for(const[o,c]of Object.entries(n)){if(!P.includes(o)){t.push(`dataPalette.${o} is not a series slot; expected one of: ${P.join(", ")}.`);continue}typeof c!="string"?t.push(`dataPalette.${o} must be a CSS color or anchor reference string.`):b(c,`dataPalette.${o}`)}}if("dataRamps"in e)if(typeof e.dataRamps!="object"||e.dataRamps===null||Array.isArray(e.dataRamps))t.push("dataRamps must be an object of named ramp declarations.");else for(const[n,o]of Object.entries(e.dataRamps)){if(g(n)?A.test(n)||t.push(`dataRamps: "${n}" is not a valid ramp name; use a lowercase slug (letters, digits, hyphens).`):t.push(`dataRamps: "${n}" is a reserved JavaScript property name and cannot be a ramp name; rename it.`),typeof o!="object"||o===null||Array.isArray(o)){t.push(`dataRamps.${n} must be a sequential or diverging ramp object.`);continue}const c=o,i=c.steps??ke;if((typeof i!="number"||!Number.isInteger(i)||i<j||i>W)&&t.push(`dataRamps.${n}.steps must be an integer from ${j} through ${W}.`),c.type==="sequential"){typeof c.source!="string"?t.push(`dataRamps.${n}.source must be a CSS color or anchor reference string.`):b(c.source,`dataRamps.${n}.source`);const f=c.lightnessStart??.95,d=c.lightnessEnd??.25;for(const[k,S]of[["lightnessStart",f],["lightnessEnd",d]])(typeof S!="number"||!Number.isFinite(S)||S<0||S>1)&&t.push(`dataRamps.${n}.${k} must be a finite number from 0 through 1.`);typeof f=="number"&&typeof d=="number"&&f<=d?t.push(`dataRamps.${n}.lightnessStart must be greater than lightnessEnd.`):typeof f=="number"&&Number.isFinite(f)&&typeof d=="number"&&Number.isFinite(d)&&typeof i=="number"&&Number.isInteger(i)&&i>=j&&i<=W&&(f-d)/(i-1)<=Y&&t.push(`dataRamps.${n} lightness bounds must leave more than ${Y} lightness between serialized stops.`);continue}if(c.type==="diverging"){typeof i=="number"&&Number.isInteger(i)&&i%2===0&&t.push(`dataRamps.${n}.steps must be odd so the neutral is the exact midpoint.`);for(const f of["start","end"])typeof c[f]!="string"?t.push(`dataRamps.${n}.${f} must be a CSS color or anchor reference string.`):b(c[f],`dataRamps.${n}.${f}`);"neutral"in c&&(typeof c.neutral!="string"?t.push(`dataRamps.${n}.neutral must be a CSS color or anchor reference string.`):b(c.neutral,`dataRamps.${n}.neutral`));continue}t.push(`dataRamps.${n}.type must be "sequential" or "diverging".`)}if("dataPalette"in e&&t.length===0){const n=We(oe,e),o={};let c=!0;for(const i of P){const f=Ae(n.dataPalette[i],n.anchors);if(!f){c=!1;break}o[i]=f}if(c)for(const i of xe(o))r.push(`dataPalette.${i.series[0]} and dataPalette.${i.series[1]} are only ${i.distance.toFixed(4)} apart under ${i.simulation} simulation (minimum ${i.threshold.toFixed(4)}); also distinguish the series with labels, shapes, or patterns.`)}function h(n,o){if(typeof n!="object"||n===null||Array.isArray(n)){t.push(`${o} must be an object.`);return}const c=n;for(const[i,f]of Object.entries(c)){const d=`${o}.${i}`;if(!H.includes(i)){t.push(`${d} is not a role; expected one of: ${H.join(", ")}. (The status family is reserved and is not a role.)`);continue}const k=i,S=Z[k];if(typeof f=="string"){y(f,d);continue}if(typeof f!="object"||f===null||Array.isArray(f)){t.push(`${d} must be a color source or a { color, \u2026slots } object.`);continue}const E=f;typeof E.color!="string"&&t.push(`${d} must declare its base "color".`);for(const[C,$]of Object.entries(E)){if(!Object.prototype.hasOwnProperty.call(S,C)||!g(C)){const x=Object.keys(S).filter(T=>T!=="color");t.push(`${d}.${C} is not a slot of the ${k} role. Declared slots: ${x.length>0?x.join(", "):"(none)"}.`);continue}typeof $!="string"?t.push(`${d}.${C} must be a color source string.`):y($,`${d}.${C}`)}}}if("roles"in e&&h(e.roles,"roles"),"contexts"in e)if(typeof e.contexts!="object"||e.contexts===null||Array.isArray(e.contexts))t.push("contexts must be an object.");else for(const[n,o]of Object.entries(e.contexts)){if(!g(n)||!A.test(n)){t.push(`contexts.${n} must be a lowercase slug matching ${A.source}.`);continue}if(typeof o!="object"||o===null||Array.isArray(o)){h(o,`contexts.${n}`);continue}const c=o,i=Object.fromEntries(Object.entries(c).filter(([f])=>f!=="lightness"));h(i,`contexts.${n}`),"lightness"in c&&l(c.lightness,`contexts.${n}.lightness`)}if("semanticMappings"in e)if(typeof e.semanticMappings!="object"||e.semanticMappings===null)t.push("semanticMappings must be an object.");else{const n=e.semanticMappings;for(const o of z)if(o in n){const c=n[o];if(typeof c!="object"||c===null){t.push(`semanticMappings.${o} must be { source, lightness }.`);continue}const i=c;typeof i.source!="string"?t.push(`semanticMappings.${o}.source must be a string.`):y(i.source,`semanticMappings.${o}.source`),(typeof i.lightness!="string"||!R.includes(i.lightness))&&t.push(`semanticMappings.${o}.lightness must be one of: ${R.join(", ")}.`)}}for(const n of["pageBackgroundImage","boxBackgroundImage","vellumBackgroundImage"])n in e&&typeof e[n]!="string"&&t.push(`${n} must be a string.`);for(const n of["pageBackgroundImageOpacity","boxBackgroundImageOpacity","vellumOpacity","vellumBackgroundImageOpacity"])if(n in e)if(typeof e[n]!="number"||!isFinite(e[n]))t.push(`${n} must be a finite number.`);else{const o=e[n];(o<0||o>1)&&t.push(`${n} must be 0\u20131 (got ${o}).`)}return{valid:t.length===0,errors:t,warnings:r}}function qe(e,t){const r=J(e),s=J(t),a=r.error!==void 0?{valid:!1,errors:[r.error],warnings:[]}:q(r.value),u=s.error!==void 0?{valid:!1,errors:[s.error],warnings:[]}:q(s.value),l=[...a.errors.map(p=>`light: ${p}`),...u.errors.map(p=>`dark: ${p}`)],m=[...a.warnings.map(p=>`light: ${p}`),...u.warnings.map(p=>`dark: ${p}`)];if(a.valid&&u.valid){const p=new Set(Object.keys(r.value?.contexts??{})),y=new Set(Object.keys(s.value?.contexts??{})),b=[...y].filter(n=>!p.has(n)).sort(),h=[...p].filter(n=>!y.has(n)).sort();(b.length>0||h.length>0)&&l.push(`contexts must declare the same names in both schemes. Missing from light: ${b.join(", ")||"(none)"}. Missing from dark: ${h.join(", ")||"(none)"}.`)}return{valid:l.length===0,errors:l,warnings:m}}const je=["anchors","angles","contexts","dataPalette","dataRamps","roles","chroma","lightness","semanticHues","semanticMappings","variantChroma"];function ze(e,t){const r={};for(const[s,a]of Object.entries(e))g(s)&&(r[s]=a);for(const[s,a]of Object.entries(t))a!==void 0&&g(s)&&(r[s]=a);for(const s of je){const a=e[s],u=t[s];if(a&&typeof a=="object"&&!Array.isArray(a)&&u&&typeof u=="object"&&!Array.isArray(u)){if(s==="anchors"){r[s]=re(a,u);continue}if(s==="contexts"){r[s]=He(a,u);continue}if(s==="dataRamps"){r[s]=ce(a,u);continue}const l={};for(const[m,p]of Object.entries(a))g(m)&&(l[m]=p);for(const[m,p]of Object.entries(u))p!==void 0&&g(m)&&(l[m]=p);r[s]=l}}return r}function Ye(...e){let t={};for(const r of e){if(!r)continue;const s=Ie(r);s&&(t=ze(t,s))}return V(t)}function le(e){return e.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\n/g,"\\n").replace(/\r/g,"\\r")}const fe={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 Xe(e){return V({...fe,pageBackgroundImage:`url("${le(e)}")`,pageBackgroundImageOpacity:.5})}function Ze(e){return V({...fe,pageBackgroundImage:`url("${le(e)}")`,pageBackgroundImageOpacity:.55})}export{A as ANCHOR_SLUG_PATTERN,K as COLOR_SOURCES,Be as DEFAULT_DARK_LIGHTNESS,we as DEFAULT_DARK_THEME,Ee as DEFAULT_LIGHT_LIGHTNESS,oe as DEFAULT_LIGHT_THEME,U as DEFAULT_SEMANTIC_MAPPINGS,R as LIGHTNESS_KEYS,je as NESTED_THEME_KEYS,H as ROLE_NAMES,Ce as ROLE_PAIRED_INK,Z as ROLE_TOKEN_PLAN,z as SEMANTIC_COLOR_NAMES,te as TOKEN_PAIRINGS,Te as VARIANT_COLOR_SOURCES,Ze as buildTaprootDarkTheme,Xe as buildTaprootLightTheme,ee as compileRoles,V as encodeTheme,Ye as layerThemes,ze as mergePartials,We as mergeTheme,X as parseAnchorSource,Ie as parseTheme,Se as resolveAnchorColor,Ae as resolveDataColorSource,Ve as semanticToCSS,Je as validateTheme,qe as validateThemePair};
|
|
1
|
+
import{ACCEPTED_COLOR_FORMS as ee,apcaContrast as et,clampChannel as le,deriveSemantic as we,gamutMapToSRGB as fe,linearRgbToOklab as tt,oklchToSRGB as nt,parseCssColor as N,parseOklch as ot,serializeOklch as ae,srgbToLinearRGB as st}from"./color-engine.js";import{computeVariants as Te,parseAnchorSource as rt,resolveAnchorColor as at,resolveMappingSource as Ee}from"./variant-engine.js";import{auditColorDistances as _e,auditDataPalette as it,DATA_SERIES_KEYS as ie,DEFAULT_DATA_PALETTE as pe,DEFAULT_DATA_RAMP_STEPS as ct,MAX_DATA_RAMP_STEPS as me,MIN_DATA_RAMP_LIGHTNESS_STEP as Ie,MIN_DATA_RAMP_STEPS as he}from"./data-colors.js";const z=/^[a-z][a-z0-9-]*$/;function de(e){return rt(e)}function Le(e,n){return at(e,n)}function ut(e,n){const t=de(e);if(t){const s=Le(n,t);return s&&N(s)?s:null}return N(e)?e:null}const Z=["canvas","ink","accent","action","structure"],He={canvas:{color:[["background","surface"],["layer1","raised1"],["layer2","raised2"],["layer3","raised3"],["layer4","raised4"]]},ink:{color:[["text","text"],["inputSelection","text"]],heading:[["headings","muted"],["headingsHover","ink"]]},accent:{color:[["linkHoverBg","raised2"],["inputSelectionBg","raised2"],["inputCaret","ink"]],text:[["link","accent"]],hover:[["linkHover","text"]]},action:{color:[["actionBackground","muted"]],ink:[["actionText","surface"]]},structure:{color:[["border","border"],["shadow","shadow"]]}},lt=new Set(["action.color"]),ft={canvas:"background",ink:"text",accent:"link",action:"actionBackground",structure:"border"},pt={"action.ink":{role:"canvas",slot:"color"}},mt=.45;function Pe(e,n){const t=Ne.actionText,s=[...U].sort((p,S)=>e[p]-e[S]||U.indexOf(p)-U.indexOf(S)),a=n?s.filter(p=>n(p)>=t.targetLc):s,u=a.length>0?a:s;let f,h=1/0;for(const p of u){const S=Math.abs(e[p]-mt);S<h&&(h=S,f=p)}return f??"muted"}function ht(e,n){const t=n[e]>.5;let s=U[0];for(const a of U)(t?n[a]<n[s]:n[a]>n[s])&&(s=a);return s}const dt={"accent.hover":"text"};function gt(e,n){const t=new Map;try{const s=se(n,e),a=(u,f,h,p)=>{const S=de(f),$=S?Le(p,S):null,x=$===null?null:N($),C=t.get(u)??[];C.some(o=>o.source===f&&o.chroma===x?.c)||(C.push({source:f,where:h,chroma:x?.c}),t.set(u,C))};for(const[u,f]of Object.entries(s.semanticMappings))f.source.startsWith("anchor:")&&a(u,f.source,"the root table",s.anchors);for(const[u,f]of Object.entries(s.contexts)){const h={};for(const S of Z){const $=f[S];$!==void 0&&(h[S]=$)}const p=se(s,{lightness:f.lightness,roles:h});for(const[S,$]of Object.entries(p.semanticMappings))$.source.startsWith("anchor:")&&a(S,$.source,`contexts.${u}`,p.anchors)}}catch{return new Map}return t}function te(e,n){if(e===void 0)return;if(typeof e=="string")return n==="color"?e:void 0;const t=e[n];return typeof t=="string"?t:void 0}function De(e,n,t,s={}){const a={},u={};for(const[f,h]of Object.entries(s.explicitMappings??{}))h!==void 0&&(u[f]=h.lightness);for(const f of Z){const h=e[f];if(h!==void 0)for(const[p,S]of Object.entries(He[f])){const $=pt[`${f}.${p}`];let x=te(h,p),C=!1;if(x===void 0){$&&(x=te(e[$.role],$.slot),x??=t[ft[$.role]]?.source,C=x!==void 0);const o=dt[`${f}.${p}`];o!==void 0&&(x??=te(h,o)),x??=te(h,"color")}if(x!==void 0)for(const[o,r]of S){let i=r;if(lt.has(`${f}.${p}`))i=Pe(n,s.actionSurfaceContrast?c=>s.actionSurfaceContrast(x,c):void 0);else if(C&&$){const c=Ne[o],m=(c&&u[c.bg])??Pe(n,s.actionSurfaceContrast?y=>s.actionSurfaceContrast(te(h,"color"),y):void 0);i=ht(m,n)}a[o]={source:x,lightness:i}}}}return a}const Ne={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}},ge=["background","layer1","layer2","layer3","layer4","actionBackground","actionText","border","shadow","text","dangerText","headings","headingsHover","link","linkHover","linkHoverBg","inputCaret","inputSelection","inputSelectionBg"],ye=["primary","analogous-left","analogous-right","complementary","split-complementary-left","split-complementary-right","triadic-left","triadic-right","danger","success","warning","info"],Q=["danger","success","warning","info"],yt=["analogous-left","analogous-right","complementary","split-complementary-left","split-complementary-right","triadic-left","triadic-right","danger","success","warning","info"],U=["surface","raised1","raised2","raised3","raised4","accent","muted","text","border","ink","shadow"],bt={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},be={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"}},G=.4;function $e(){const e={};for(const n of ge)e[n]={min:0,max:G};return e}const Fe={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,info:244},variantChroma:{},intents:{},chroma:$e(),semanticMappings:{...be},anchors:{},roles:{},contexts:{},dataPalette:{...pe},dataRamps:{}},Se={...Fe,chroma:$e(),semanticMappings:{...be},anchors:{},roles:{},contexts:{},dataPalette:{...pe},dataRamps:{},lightness:{...bt}},We={...Fe,chroma:$e(),semanticMappings:{...be},anchors:{},roles:{},contexts:{},dataPalette:{...pe},dataRamps:{},lightness:{...$t}},ce=new WeakMap;ce.set(Se,new Set),ce.set(We,new Set);const je=new Set(["__proto__","constructor","prototype"]);function A(e){return!je.has(e)}function St(e,n){return je.has(e)?void 0:n}function Dt(e){return`--esp-color-${e.replace(/([A-Z])/g,"-$1").replace(/(\d)/g,"-$1").toLowerCase()}`}function xt(e){try{const n=atob(e),t=JSON.parse(n,St);return typeof t!="object"||t===null||Array.isArray(t)?null:t}catch{return null}}function xe(e){return btoa(JSON.stringify(e))}function kt(e){const n={};for(const t of Q){const s=e[t];typeof s=="string"&&(n[t]=s.startsWith("anchor:")?s:ne(s))}return n}function ne(e){if(ot(e))return e;const n=N(e);return n?ae(n):e}function Ke(e,n){const t={};for(const[s,a]of Object.entries(e))A(s)&&(t[s]=a);if(!n)return t;for(const[s,a]of Object.entries(n)){if(a===void 0||!A(s))continue;const u=t[s];if(u!==void 0&&typeof a=="object"&&a!==null){const f={};if(typeof u=="string")f.color=u;else for(const[h,p]of Object.entries(u))A(h)&&(f[h]=p);for(const[h,p]of Object.entries(a))p!==void 0&&A(h)&&(f[h]=p);t[s]=f;continue}t[s]=a}return t}function ze(e){if(typeof e!="object"||e===null||Array.isArray(e))return null;const n=e,t={};for(const s of Z){const a=n[s];a!==void 0&&(t[s]=a)}if(typeof n.lightness=="object"&&n.lightness!==null&&!Array.isArray(n.lightness)){const s={};for(const a of U){const u=n.lightness[a];u!==void 0&&(s[a]=u)}t.lightness=s}return t}function At(e,n){const t={};for(const[s,a]of Object.entries(e)){if(!A(s)||!z.test(s))continue;const u=ze(a);u&&(t[s]=u)}if(!n)return t;for(const[s,a]of Object.entries(n)){if(!A(s)||!z.test(s)||a===void 0)continue;const u=ze(a);if(!u)continue;const f=t[s];t[s]={...f??{},...u,...f?.lightness||u.lightness?{lightness:{...f?.lightness,...u.lightness}}:{}}}return t}function J(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function Y(e){const n={};for(const[t,s]of Object.entries(e))s!==void 0&&A(t)&&(n[t]=s);return n}function Ue(e){if(!J(e))return e;const n=Y(e);return J(e.lightness)&&(n.lightness=Y(e.lightness)),n}function vt(e,n){const t={};for(const[s,a]of Object.entries(e))A(s)&&(t[s]=Ue(a));if(!n)return t;for(const[s,a]of Object.entries(n)){if(!A(s)||a===void 0)continue;const u=t[s];if(!J(u)||!J(a)){t[s]=Ue(a);continue}const f={...Y(u),...Y(a)};J(u.lightness)&&J(a.lightness)?f.lightness={...Y(u.lightness),...Y(a.lightness)}:J(a.lightness)&&(f.lightness=Y(a.lightness)),t[s]=f}return t}function Rt(e){const n={};for(const[t,s]of Object.entries(e)){if(!A(t))continue;if(typeof s=="string"){n[t]=ne(s);continue}const a={};for(const[u,f]of Object.entries(s))A(u)&&(a[u]=typeof f=="string"?ne(f):f);n[t]=a}return n}function oe(e){return typeof e!="string"?"":e.startsWith("anchor:")?e:ne(e)}function Ot(e){const n={};for(const t of ie)n[t]=oe(e[t]);return n}function Ge(e,n){const t={};for(const[s,a]of Object.entries(e))A(s)&&z.test(s)&&a&&typeof a=="object"&&!Array.isArray(a)&&(t[s]={...a});if(!n)return t;for(const[s,a]of Object.entries(n)){if(!A(s)||!z.test(s)||!a||typeof a!="object"||Array.isArray(a))continue;const u=t[s],f=u!==void 0&&a.type!==void 0&&a.type!==u.type;t[s]={...f?{}:u??{},...a}}return t}function Ct(e){const n={};for(const[t,s]of Object.entries(e))if(A(t)){if(s.type==="sequential"&&typeof s.source=="string"){n[t]={...s,source:oe(s.source)};continue}if(s.type==="diverging"&&typeof s.start=="string"&&typeof s.end=="string"){n[t]={...s,start:oe(s.start),end:oe(s.end),...typeof s.neutral=="string"?{neutral:oe(s.neutral)}:{}};continue}n[t]={...s}}return n}function Ve(e){const n=N(e.seedColor);if(!n)return;const t=Te(n,e);return(s,a)=>{const u=Ee(s,t,e.anchors)??t.primary,f=e.chroma.actionBackground,h=we(u,e.lightness[a],f.min,f.max),p={l:h.l>.5?0:1,c:0,h:0};return Math.abs(et(p,h))}}function Mt(e){const n=ce.get(e);if(n)return new Set(n);const t=new Set,s=De(e.roles,e.lightness,e.semanticMappings,{actionSurfaceContrast:Ve(e)});for(const[a,u]of Object.entries(s)){const f=e.semanticMappings[a];(f.source!==u.source||f.lightness!==u.lightness)&&t.add(a)}return t}function se(e,n){const t={...e.roles,...n.roles},s=At(e.contexts,n.contexts),a={...e.lightness,...n.lightness},u=Rt(Ke(e.anchors,n.anchors)),f=typeof n.seedColor=="string"?ne(n.seedColor):e.seedColor,h=n.semanticMappings,p={...e.angles,...n.angles},S={...e.semanticHues,...n.semanticHues},$={...e.variantChroma,...n.variantChroma},x=kt({...e.intents,...n.intents}),C=re(e.chroma,n.chroma),o=Ot(re(e.dataPalette,n.dataPalette)),r=Ct(Ge(e.dataRamps,n.dataRamps)),i=Mt(e),c=new Set(i),m={};for(const g of i)m[g]=e.semanticMappings[g];for(const[g,b]of Object.entries(h??{}))b!==void 0&&(c.add(g),m[g]=b);const y=re(e.semanticMappings,h),I=Ve({angles:p,anchors:u,chroma:C,intents:x,lightness:a,seedColor:f,semanticHues:S,variantChroma:$}),D=De(t,a,y,{explicitMappings:m,actionSurfaceContrast:I}),W={};for(const[g,b]of Object.entries(D))c.has(g)||(W[g]=b);const l=re(re(e.semanticMappings,W),h),d={...e,seedColor:f,fontBody:n.fontBody??e.fontBody,fontHeadings:n.fontHeadings??e.fontHeadings,fontBrand:n.fontBrand??e.fontBrand,fontMonospace:n.fontMonospace??e.fontMonospace,fontWeightBody:String(n.fontWeightBody??e.fontWeightBody),fontWeightHeadings:String(n.fontWeightHeadings??e.fontWeightHeadings),fontWeightBrand:String(n.fontWeightBrand??e.fontWeightBrand),fontWeightMonospace:String(n.fontWeightMonospace??e.fontWeightMonospace),stylesheets:n.stylesheets??[...e.stylesheets],rootFontSize:n.rootFontSize??e.rootFontSize,typeRatio:n.typeRatio??e.typeRatio,spaceRatio:n.spaceRatio??e.spaceRatio,borderRadius:n.borderRadius??e.borderRadius,viewportMin:n.viewportMin??e.viewportMin,viewportMax:n.viewportMax??e.viewportMax,angles:p,semanticHues:S,variantChroma:$,intents:x,lightness:a,chroma:C,semanticMappings:l,anchors:u,roles:t,contexts:s,dataPalette:o,dataRamps:r};return n.pageBackgroundImage!==void 0&&(d.pageBackgroundImage=n.pageBackgroundImage),n.pageBackgroundImageOpacity!==void 0&&(d.pageBackgroundImageOpacity=n.pageBackgroundImageOpacity),n.boxBackgroundImage!==void 0&&(d.boxBackgroundImage=n.boxBackgroundImage),n.boxBackgroundImageOpacity!==void 0&&(d.boxBackgroundImageOpacity=n.boxBackgroundImageOpacity),n.vellumOpacity!==void 0&&(d.vellumOpacity=n.vellumOpacity),n.vellumBackgroundImage!==void 0&&(d.vellumBackgroundImage=n.vellumBackgroundImage),n.vellumBackgroundImageOpacity!==void 0&&(d.vellumBackgroundImageOpacity=n.vellumBackgroundImageOpacity),ce.set(d,new Set(c)),d}function re(e,n){if(!n)return{...e};const t={...e};for(const s of Object.keys(n)){const a=n[s];a!==void 0&&(t[s]=a)}return t}function ke(e){let n;try{n=atob(e)}catch{return{error:"Failed to decode Base64 string."}}let t;try{t=JSON.parse(n)}catch{return{error:"Decoded string is not valid JSON."}}return typeof t!="object"||t===null||Array.isArray(t)?{error:"Theme must be a JSON object."}:{value:t}}function Nt(e){const n=ke(e);return n.error!==void 0?{valid:!1,errors:[n.error],warnings:[]}:Ae(n.value)}function Ae(e,n=Se){const t=[],s=[];"seedColor"in e&&(typeof e.seedColor!="string"?t.push("seedColor must be a string."):N(e.seedColor)||t.push(`seedColor is not a valid CSS color: "${e.seedColor}". Accepted forms: ${ee}.`));for(const o of["fontBody","fontHeadings","fontBrand","fontMonospace"])o in e&&typeof e[o]!="string"&&t.push(`${o} must be a string.`);const a=["normal","bold","lighter","bolder"],u=["inherit","initial","unset","revert","revert-layer"];for(const o of["fontWeightBody","fontWeightHeadings","fontWeightBrand","fontWeightMonospace"])if(o in e){const r=e[o];if(typeof r=="number")(r<1||r>1e3)&&t.push(`${o} numeric value must be 1\u20131000 (got ${r}).`);else if(typeof r=="string"){const i=a.includes(r)||u.includes(r);if(/^\d+$/.test(r)){const m=Number(r);(m<1||m>1e3)&&t.push(`${o} numeric value must be 1\u20131000 (got "${r}").`)}else i||s.push(`${o} = "${r}" is not a standard font-weight value.`)}else t.push(`${o} must be a string or number.`)}"stylesheets"in e&&(Array.isArray(e.stylesheets)?e.stylesheets.some(o=>typeof o!="string")&&t.push("Every entry in stylesheets must be a string."):t.push("stylesheets must be an array of strings."));const f=[["rootFontSize",1,100],["borderRadius",0,10],["viewportMin",100,1e4],["viewportMax",200,1e4]];for(const[o,r,i]of f)if(o in e)if(typeof e[o]!="number"||!isFinite(e[o]))t.push(`${o} must be a finite number.`);else{const c=e[o];r!==void 0&&c<r&&t.push(`${o} must be \u2265 ${r} (got ${c}).`),i!==void 0&&c>i&&s.push(`${o} = ${c} is unusually high (max ${i}).`)}for(const o of["typeRatio","spaceRatio"])if(o in e)if(typeof e[o]!="number"||!isFinite(e[o]))t.push(`${o} must be a finite number.`);else{const r=e[o];r<=1&&t.push(`${o} must be > 1 (got ${r}).`);const i=o==="typeRatio"?1.3:2;r>i&&s.push(`${o} = ${r} is very high (max ${i}); scales may be extreme.`)}if("viewportMin"in e&&"viewportMax"in e){const o=e.viewportMin,r=e.viewportMax;typeof o=="number"&&typeof r=="number"&&o>=r&&t.push(`viewportMin (${o}) must be less than viewportMax (${r}).`)}if("angles"in e)if(typeof e.angles!="object"||e.angles===null)t.push("angles must be an object.");else{const o=e.angles;for(const r of["analogous","complementary","splitComplementary","triadic"])if(r in o)if(typeof o[r]!="number"||!isFinite(o[r]))t.push(`angles.${r} must be a finite number.`);else{const i=o[r];(i<0||i>360)&&s.push(`angles.${r} = ${i} is outside 0\u2013360.`)}}if("semanticHues"in e)if(typeof e.semanticHues!="object"||e.semanticHues===null)t.push("semanticHues must be an object.");else{const o=e.semanticHues;for(const r of["danger","success","warning","info"])if(r in o)if(typeof o[r]!="number"||!isFinite(o[r]))t.push(`semanticHues.${r} must be a finite number.`);else{const i=o[r];(i<0||i>360)&&s.push(`semanticHues.${r} = ${i} is outside 0\u2013360.`)}}if("variantChroma"in e)if(typeof e.variantChroma!="object"||e.variantChroma===null)t.push("variantChroma must be an object.");else{const o=e.variantChroma;for(const r of yt)if(r in o)if(typeof o[r]!="number"||!isFinite(o[r]))t.push(`variantChroma["${r}"] must be a finite number.`);else{const i=o[r];i<0&&t.push(`variantChroma["${r}"] must be \u2265 0 (got ${i}).`),i>G&&s.push(`variantChroma["${r}"] = ${i} exceeds ${G}.`)}}function h(o,r){if(typeof o!="object"||o===null||Array.isArray(o)){t.push(`${r} must be an object.`);return}const i=o;for(const c of U)if(c in i)if(typeof i[c]!="number"||!isFinite(i[c]))t.push(`${r}.${c} must be a finite number.`);else{const m=i[c];(m<0||m>1)&&t.push(`${r}.${c} must be 0\u20131 (got ${m}).`)}}if("lightness"in e&&h(e.lightness,"lightness"),"chroma"in e)if(typeof e.chroma!="object"||e.chroma===null)t.push("chroma must be an object.");else{const o=e.chroma,r=gt(e,n);for(const i of ge)if(i in o){const c=o[i];if(typeof c!="object"||c===null){t.push(`chroma.${i} must be { min, max }.`);continue}const m=c;for(const I of r.get(i)??[])I.chroma!==void 0&&typeof m.min=="number"&&typeof m.max=="number"&&(I.chroma<m.min-1e-9||I.chroma>m.max+1e-9)&&s.push(`chroma.${i} clamps the anchor-sourced token ${i} ("${I.source}", effective in ${I.where}) and moves it off its declared swatch. Remove the band if that is unintended \u2014 anchors otherwise keep their own chroma.`);const y=c;(typeof y.min!="number"||y.min<0)&&t.push(`chroma.${i}.min must be \u2265 0.`),(typeof y.max!="number"||y.max<0||y.max>G)&&t.push(`chroma.${i}.max must be 0\u2013${G}.`),typeof y.min=="number"&&typeof y.max=="number"&&y.min>y.max&&t.push(`chroma.${i}.min (${y.min}) must be \u2264 max (${y.max}).`)}}if("anchors"in e)if(typeof e.anchors!="object"||e.anchors===null||Array.isArray(e.anchors))t.push("anchors must be an object of named colors.");else for(const[o,r]of Object.entries(e.anchors))if(A(o)?z.test(o)||t.push(`anchors: "${o}" is not a valid anchor name; use a lowercase slug (letters, digits, hyphens).`):t.push(`anchors: "${o}" is a reserved JavaScript property name and cannot be an anchor name; rename it.`),ye.includes(o)&&t.push(`anchors: "${o}" collides with a reserved color source name.`),typeof r=="string")N(r)||t.push(`anchors.${o} is not a valid CSS color: "${r}". Accepted forms: ${ee}.`);else if(typeof r=="object"&&r!==null&&!Array.isArray(r)){const i=r;typeof i.color!="string"&&t.push(`anchors.${o} must declare its base "color".`);for(const[c,m]of Object.entries(i))A(c)?c!=="color"&&!z.test(c)&&t.push(`anchors.${o}: "${c}" is not a valid slot name; use a lowercase slug.`):t.push(`anchors.${o}: "${c}" is a reserved JavaScript property name and cannot be a slot name; rename it.`),typeof m!="string"?t.push(`anchors.${o}.${c} must be a CSS color string.`):N(m)||t.push(`anchors.${o}.${c} is not a valid CSS color: "${m}". Accepted forms: ${ee}.`)}else t.push(`anchors.${o} must be a color string or a { color, \u2026slots } object.`);const p=new Map;if("anchors"in e&&typeof e.anchors=="object"&&e.anchors!==null&&!Array.isArray(e.anchors))for(const[o,r]of Object.entries(e.anchors))p.set(o,r);function S(o,r){const i=de(o);if(!i){t.push(`${r} "${o}" is not valid anchor syntax; use anchor:<name> or anchor:<name>.<slot>.`);return}if(!p.has(i.name)){const c=[...p.keys()];t.push(`${r} references undeclared anchor "${i.name}". Declared anchors: ${c.length>0?c.join(", "):"(none)"}.`);return}if(i.slot!==void 0){const c=p.get(i.name);if(typeof(typeof c=="object"&&c!==null&&!Array.isArray(c)?c[i.slot]:void 0)!="string"){const y=typeof c=="object"&&c!==null?Object.keys(c).filter(I=>I!=="color"):[];t.push(`${r} references unknown slot "${i.slot}" on anchor "${i.name}". Declared slots: ${y.length>0?y.join(", "):"(none)"}.`)}}}function $(o,r){if(o.startsWith("anchor:")){S(o,r);return}ye.includes(o)||t.push(`${r} must be one of: ${ye.join(", ")}, or a declared anchor as anchor:<name> / anchor:<name>.<slot>.`)}if("intents"in e)if(typeof e.intents!="object"||e.intents===null||Array.isArray(e.intents))t.push("intents must be an object.");else for(const[o,r]of Object.entries(e.intents)){const i=`intents.${o}`;if(!Q.includes(o)){t.push(`${i} is not a status family; expected one of: ${Q.join(", ")}.`);continue}if(typeof r!="string"){t.push(`${i} must be a string (a CSS color or an anchor: reference).`);continue}if(r.startsWith("anchor:")){S(r,i);continue}N(r)||t.push(`${i} "${r}" is not a supported color form or anchor: reference. Accepted forms: ${ee}, or anchor:<name> / anchor:<name>.<slot>. An override retunes a family with a declared color; it never points one family at another \u2014 retune, never reassign.`)}function x(o,r){if(o.startsWith("anchor:")){S(o,r);return}N(o)||t.push(`${r} is not a valid CSS color: "${o}". Accepted forms: ${ee}, or a declared anchor as anchor:<name> / anchor:<name>.<slot>.`)}if("dataPalette"in e)if(typeof e.dataPalette!="object"||e.dataPalette===null||Array.isArray(e.dataPalette))t.push("dataPalette must be an object with series1\u2013series8 color values.");else{const o=e.dataPalette;for(const[r,i]of Object.entries(o)){if(!ie.includes(r)){t.push(`dataPalette.${r} is not a series slot; expected one of: ${ie.join(", ")}.`);continue}typeof i!="string"?t.push(`dataPalette.${r} must be a CSS color or anchor reference string.`):x(i,`dataPalette.${r}`)}}if("dataRamps"in e)if(typeof e.dataRamps!="object"||e.dataRamps===null||Array.isArray(e.dataRamps))t.push("dataRamps must be an object of named ramp declarations.");else for(const[o,r]of Object.entries(e.dataRamps)){if(A(o)?z.test(o)||t.push(`dataRamps: "${o}" is not a valid ramp name; use a lowercase slug (letters, digits, hyphens).`):t.push(`dataRamps: "${o}" is a reserved JavaScript property name and cannot be a ramp name; rename it.`),typeof r!="object"||r===null||Array.isArray(r)){t.push(`dataRamps.${o} must be a sequential or diverging ramp object.`);continue}const i=r,c=i.steps??ct;if((typeof c!="number"||!Number.isInteger(c)||c<he||c>me)&&t.push(`dataRamps.${o}.steps must be an integer from ${he} through ${me}.`),i.type==="sequential"){typeof i.source!="string"?t.push(`dataRamps.${o}.source must be a CSS color or anchor reference string.`):x(i.source,`dataRamps.${o}.source`);const m=i.lightnessStart??.95,y=i.lightnessEnd??.25;for(const[I,D]of[["lightnessStart",m],["lightnessEnd",y]])(typeof D!="number"||!Number.isFinite(D)||D<0||D>1)&&t.push(`dataRamps.${o}.${I} must be a finite number from 0 through 1.`);typeof m=="number"&&typeof y=="number"&&m<=y?t.push(`dataRamps.${o}.lightnessStart must be greater than lightnessEnd.`):typeof m=="number"&&Number.isFinite(m)&&typeof y=="number"&&Number.isFinite(y)&&typeof c=="number"&&Number.isInteger(c)&&c>=he&&c<=me&&(m-y)/(c-1)<=Ie&&t.push(`dataRamps.${o} lightness bounds must leave more than ${Ie} lightness between serialized stops.`);continue}if(i.type==="diverging"){typeof c=="number"&&Number.isInteger(c)&&c%2===0&&t.push(`dataRamps.${o}.steps must be odd so the neutral is the exact midpoint.`);for(const m of["start","end"])typeof i[m]!="string"?t.push(`dataRamps.${o}.${m} must be a CSS color or anchor reference string.`):x(i[m],`dataRamps.${o}.${m}`);"neutral"in i&&(typeof i.neutral!="string"?t.push(`dataRamps.${o}.neutral must be a CSS color or anchor reference string.`):x(i.neutral,`dataRamps.${o}.neutral`));continue}t.push(`dataRamps.${o}.type must be "sequential" or "diverging".`)}if("dataPalette"in e&&t.length===0){const o=se(Se,e),r={};let i=!0;for(const c of ie){const m=ut(o.dataPalette[c],o.anchors);if(!m){i=!1;break}r[c]=m}if(i)for(const c of it(r))s.push(`dataPalette.${c.series[0]} and dataPalette.${c.series[1]} are only ${c.distance.toFixed(4)} apart under ${c.simulation} simulation (minimum ${c.threshold.toFixed(4)}); also distinguish the series with labels, shapes, or patterns.`)}function C(o,r){if(typeof o!="object"||o===null||Array.isArray(o)){t.push(`${r} must be an object.`);return}const i=o;for(const[c,m]of Object.entries(i)){const y=`${r}.${c}`;if(!Z.includes(c)){t.push(`${y} is not a role; expected one of: ${Z.join(", ")}. (The status family is reserved and is not a role.)`);continue}const I=c,D=He[I];if(typeof m=="string"){$(m,y);continue}if(typeof m!="object"||m===null||Array.isArray(m)){t.push(`${y} must be a color source or a { color, \u2026slots } object.`);continue}const W=m;typeof W.color!="string"&&t.push(`${y} must declare its base "color".`);for(const[l,d]of Object.entries(W)){if(!Object.prototype.hasOwnProperty.call(D,l)||!A(l)){const g=Object.keys(D).filter(b=>b!=="color");t.push(`${y}.${l} is not a slot of the ${I} role. Declared slots: ${g.length>0?g.join(", "):"(none)"}.`);continue}typeof d!="string"?t.push(`${y}.${l} must be a color source string.`):$(d,`${y}.${l}`)}}}if("roles"in e&&C(e.roles,"roles"),"contexts"in e)if(typeof e.contexts!="object"||e.contexts===null||Array.isArray(e.contexts))t.push("contexts must be an object.");else for(const[o,r]of Object.entries(e.contexts)){if(!A(o)||!z.test(o)){t.push(`contexts.${o} must be a lowercase slug matching ${z.source}.`);continue}if(typeof r!="object"||r===null||Array.isArray(r)){C(r,`contexts.${o}`);continue}const i=r,c=Object.fromEntries(Object.entries(i).filter(([m])=>m!=="lightness"));C(c,`contexts.${o}`),"lightness"in i&&h(i.lightness,`contexts.${o}.lightness`)}if("semanticMappings"in e)if(typeof e.semanticMappings!="object"||e.semanticMappings===null)t.push("semanticMappings must be an object.");else{const o=e.semanticMappings;for(const r of ge)if(r in o){const i=o[r];if(typeof i!="object"||i===null){t.push(`semanticMappings.${r} must be { source, lightness }.`);continue}const c=i;typeof c.source!="string"?t.push(`semanticMappings.${r}.source must be a string.`):$(c.source,`semanticMappings.${r}.source`),(typeof c.lightness!="string"||!U.includes(c.lightness))&&t.push(`semanticMappings.${r}.lightness must be one of: ${U.join(", ")}.`)}}for(const o of["pageBackgroundImage","boxBackgroundImage","vellumBackgroundImage"])o in e&&typeof e[o]!="string"&&t.push(`${o} must be a string.`);for(const o of["pageBackgroundImageOpacity","boxBackgroundImageOpacity","vellumOpacity","vellumBackgroundImageOpacity"])if(o in e)if(typeof e[o]!="number"||!isFinite(e[o]))t.push(`${o} must be a finite number.`);else{const r=e[o];(r<0||r>1)&&t.push(`${o} must be 0\u20131 (got ${r}).`)}return s.push(...Bt(e,n)),{valid:t.length===0,errors:t,warnings:s}}const O=.045;function Bt(e,n){try{return wt(e,n)}catch{return[]}}function wt(e,n){const t=se(n,e),s=qe(t),a=[...s],u=new Set(s);for(const[f,h]of Object.entries(t.contexts)){const p={};for(const $ of Z){const x=h[$];x!==void 0&&(p[$]=x)}const S=se(t,{lightness:h.lightness,roles:p});for(const $ of qe(S))u.has($)||a.push(`contexts.${f}: ${$}`)}return a}function Tt(e){const n=nt(fe(e)),t=st(n);return tt({r:le(t.r),g:le(t.g),b:le(t.b)})}function q(e,n){return Math.hypot(e.L-n.L,e.a-n.a,e.b-n.b)}function V(e){return Tt(N(ae(fe(e))))}function Je(e){return(Math.floor(e*1e4)/1e4).toFixed(4)}const X=2,Ye=1e-4;function qe(e){const n=N(e.seedColor);if(!n)return[];const t=Te(n,e),s=e.semanticMappings.actionBackground,a=e.chroma.actionBackground,u=e.lightness[s.lightness],f=(l,d,g,b)=>fe(we(l,d,g,b)),h=Q.map(l=>({name:l,base:t[l]})),p=[];if(Q.includes(s.source))p.push(`actionBackground is sourced from the "${s.source}" status family: ordinary and ${s.source}-intent action surfaces render identically (their labels may still differ). Remap the action to a non-status source \u2014 retuning "${s.source}" via intents moves both colors together.`);else{const l=Ee(s.source,t,e.anchors);l&&h.push({name:"action",base:l})}const S=_e(h.map(({name:l,base:d})=>[l,ae(f(d,u,a.min,a.max))]),O,["normal"]);if(S.length===0)return p;const $=new Map,x=(l,d)=>{const g=`${l}:${d}`;let b=$.get(g);if(!b){b=[];for(let w=0;w<360;w+=X)b.push(V({l,c:d,h:w}));$.set(g,b)}return b},C=O-.002,o=(l,d,g,b)=>{const w=Math.hypot(l.a,l.b),M=Math.atan2(l.b,l.a)*180/Math.PI+180;let E=0;for(const B of g===b?[b]:[g,b]){if(B+w<O-1e-4)continue;let L=M,R=q(V({l:d,c:B,h:M}),l);if(R>=O)return R;const P=x(d,B);for(let v=0;v<P.length;v+=1){const k=q(P[v],l);if(k>=O)return k;k>R&&(R=k,L=v*X)}let H=L;for(let v=L-X;v<=L+X;v+=.1){const k=q(V({l:d,c:B,h:v}),l);if(k>=O)return k;k>R&&(R=k,H=v)}if(R>=C)for(let v=H-.1;v<=H+.1;v+=.001){const k=q(V({l:d,c:B,h:v}),l);if(k>=O)return k;k>R&&(R=k)}R>E&&(E=R)}return E},r=(l,d,g)=>{const b=d===g?[g]:[d,g];let w=0;for(const M of b)for(const E of b){if(M+E<O-1e-4)continue;const B=x(l,M),L=x(l,E);let R=0,P=0,H=-1;for(let _=0;_<B.length;_+=1)for(let F=0;F<L.length;F+=1){const j=q(B[_],L[F]);if(j>=O)return j;j>H&&(H=j,R=_*X,P=F*X)}const v=(_,F,j,ve)=>{const Re=[];for(let K=F-j;K<=F+j;K+=ve)Re.push({h:K,lab:V({l,c:E,h:K})});let ue=-1,Oe=_,Ce=F;for(let K=_-j;K<=_+j;K+=ve){const Qe=V({l,c:M,h:K});for(const Me of Re){const Be=q(Qe,Me.lab);Be>ue&&(ue=Be,Oe=K,Ce=Me.h)}}return{distance:ue,hueA:Oe,hueB:Ce}},k=v(R,P,X,.1);if(k.distance>=O)return k.distance;let T=Math.max(H,k.distance);if(T>=C){const _=v(k.hueA,k.hueB,.1,.001);if(_.distance>T&&(T=_.distance),T>=O)return T}T>w&&(w=T)}return w},i=l=>Q.includes(l),c=(l,d,g,b,w)=>{const M=V(f(l.base,g,b,w)),E=V(f(d.base,g,b,w));if(q(M,E)>=O)return{outcome:"direct"};const B=i(l.name)&&i(d.name),L=[l,d].filter(H=>i(H.name)),R=B?"one of them":`"${i(l.name)?l.name:d.name}"`;let P;for(const H of L){const v=o(H===l?E:M,g,b,w);if(v>=O)return{outcome:"retune",target:R};v>=O-Ye&&(P=P??R)}if(B){const H=r(g,b,w);if(H>=O)return{outcome:"retune",target:"both"};H>=O-Ye&&(P=P??"both")}return P!==void 0?{outcome:"near",target:P}:{outcome:"no"}},m=l=>l.outcome==="direct"?4:l.outcome==="retune"?l.target==="both"?2:3:l.outcome==="near"?1:0,y=l=>[...l].sort().join("|"),I=new Set(_e(h.map(({name:l,base:d})=>[l,ae(f(d,u,0,G))]),O,["normal"]).map(l=>y(l.pair))),D=new Map(h.map(l=>[l.name,l])),W=new Map;for(const{pair:l,distance:d}of S){const g=D.get(l[0]),b=D.get(l[1]),w=i(g.name)&&i(b.name),M=c(g,b,u,a.min,a.max);if(M.outcome==="direct"||M.outcome==="retune"){const T=M.target??(w?"one of them":`"${i(g.name)?g.name:b.name}"`);I.has(y(l))?p.push(`Status colors "${l[0]}" and "${l[1]}" are hard to distinguish under normal vision (distance ${Je(d)} < ${O}); status meanings must stay distinguishable \u2014 retune ${T} via intents.`):p.push(`Status colors "${l[0]}" and "${l[1]}" are hard to distinguish as rendered (distance ${Je(d)} < ${O}); the actionBackground chroma band ({ min: ${a.min}, max: ${a.max} }) pushes them together \u2014 widen the band, or retune ${T} via intents.`);continue}const E=c(g,b,u,0,G);let B={outcome:"no"};for(let T=1;T<=19&&B.outcome!=="direct";T+=1){const _=T*.05;if(Math.abs(_-u)<.001)continue;const F=c(g,b,_,a.min,a.max);m(F)>m(B)&&(B=F)}let L={outcome:"no"};const R=E.outcome==="direct"||E.outcome==="retune",P=B.outcome==="direct"||B.outcome==="retune";if(!R&&!P)for(let T=1;T<=19&&L.outcome!=="direct";T+=1){const _=c(g,b,T*.05,0,G);m(_)>m(L)&&(L=_)}const H=Et(E,B,L),v=`${M.outcome}|${H}`;let k=W.get(v);k||(k=[],W.set(v,k)),k.push(l)}for(const[l,d]of W){const g=l.indexOf("|"),b=l.slice(0,g),w=l.slice(g+1),M=d.map(([L,R])=>`"${L}"/"${R}"`),E=M.length>1?`${M.slice(0,-1).join(", ")} and ${M[M.length-1]}`:M[0],B=b==="near"?`Status colors ${E} may not separate by retuning as rendered: at the action stop's lightness (${u}) with the actionBackground chroma band ({ min: ${a.min}, max: ${a.max} }), the closest reachable retune found comes within the audit's search margin of the ${O} threshold`:`Status colors ${E} cannot be separated as rendered: at the action stop's lightness (${u}) with the actionBackground chroma band ({ min: ${a.min}, max: ${a.max} }), no intent retuning can pull ${d.length>1?"these pairs":"the pair"} ${O} apart`;p.push(B+w)}return p}function Et(e,n,t){if(e.outcome==="direct"&&n.outcome==="direct")return" \u2014 widen the chroma band or move the action lightness stop.";if(e.outcome==="direct")return n.outcome==="no"?"; no other action lightness stop can help while the band holds \u2014 widen the chroma band.":" \u2014 widen the chroma band.";if(n.outcome==="direct")return e.outcome==="no"?"; no wider chroma band can help at this lightness \u2014 move the action lightness stop.":" \u2014 move the action lightness stop.";if(e.outcome==="retune"&&n.outcome==="retune")return` \u2014 widen the chroma band or move the action lightness stop, then retune ${e.target} via intents.`;if(e.outcome==="retune")return n.outcome==="no"?`; no other action lightness stop can help while the band holds \u2014 widen the chroma band, then retune ${e.target} via intents.`:` \u2014 widen the chroma band, then retune ${e.target} via intents.`;if(n.outcome==="retune")return e.outcome==="no"?`; no wider chroma band can help at this lightness \u2014 move the action lightness stop, then retune ${n.target} via intents.`:` \u2014 move the action lightness stop, then retune ${n.target} via intents.`;const s=e.outcome==="no"&&n.outcome==="no"?"; neither a wider chroma band alone nor another stop alone can help":"; neither a wider chroma band alone nor another stop alone provably helps";return t.outcome==="direct"?`${s} \u2014 change the band and the stop together.`:t.outcome==="retune"?`${s} \u2014 change the band and the stop together, then retune ${t.target} via intents.`:"; no explored band or stop change provably separates this pair."}function Ft(e,n){const t=ke(e),s=ke(n),a=t.error!==void 0?{valid:!1,errors:[t.error],warnings:[]}:Ae(t.value),u=s.error!==void 0?{valid:!1,errors:[s.error],warnings:[]}:Ae(s.value,We),f=[...a.errors.map(p=>`light: ${p}`),...u.errors.map(p=>`dark: ${p}`)],h=[...a.warnings.map(p=>`light: ${p}`),...u.warnings.map(p=>`dark: ${p}`)];if(a.valid&&u.valid){const p=new Set(Object.keys(t.value?.contexts??{})),S=new Set(Object.keys(s.value?.contexts??{})),$=[...S].filter(C=>!p.has(C)).sort(),x=[...p].filter(C=>!S.has(C)).sort();($.length>0||x.length>0)&&f.push(`contexts must declare the same names in both schemes. Missing from light: ${$.join(", ")||"(none)"}. Missing from dark: ${x.join(", ")||"(none)"}.`)}return{valid:f.length===0,errors:f,warnings:h}}const _t=["anchors","angles","contexts","dataPalette","dataRamps","intents","roles","chroma","lightness","semanticHues","semanticMappings","variantChroma"];function It(e,n){const t={};for(const[s,a]of Object.entries(e))A(s)&&(t[s]=a);for(const[s,a]of Object.entries(n))a!==void 0&&A(s)&&(t[s]=a);for(const s of _t){const a=e[s],u=n[s];if(a&&typeof a=="object"&&!Array.isArray(a)&&u&&typeof u=="object"&&!Array.isArray(u)){if(s==="anchors"){t[s]=Ke(a,u);continue}if(s==="contexts"){t[s]=vt(a,u);continue}if(s==="dataRamps"){t[s]=Ge(a,u);continue}const f={};for(const[h,p]of Object.entries(a))A(h)&&(f[h]=p);for(const[h,p]of Object.entries(u))p!==void 0&&A(h)&&(f[h]=p);t[s]=f}}return t}function Wt(...e){let n={};for(const t of e){if(!t)continue;const s=xt(t);s&&(n=It(n,s))}return xe(n)}function Xe(e){return e.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\n/g,"\\n").replace(/\r/g,"\\r")}const Ze={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 jt(e){return xe({...Ze,pageBackgroundImage:`url("${Xe(e)}")`,pageBackgroundImageOpacity:.5})}function Kt(e){return xe({...Ze,pageBackgroundImage:`url("${Xe(e)}")`,pageBackgroundImageOpacity:.55})}export{z as ANCHOR_SLUG_PATTERN,ye as COLOR_SOURCES,$t as DEFAULT_DARK_LIGHTNESS,We as DEFAULT_DARK_THEME,bt as DEFAULT_LIGHT_LIGHTNESS,Se as DEFAULT_LIGHT_THEME,be as DEFAULT_SEMANTIC_MAPPINGS,U as LIGHTNESS_KEYS,_t as NESTED_THEME_KEYS,Z as ROLE_NAMES,pt as ROLE_PAIRED_INK,He as ROLE_TOKEN_PLAN,ge as SEMANTIC_COLOR_NAMES,Q as STATUS_COLOR_SOURCES,Ne as TOKEN_PAIRINGS,yt as VARIANT_COLOR_SOURCES,Kt as buildTaprootDarkTheme,jt as buildTaprootLightTheme,De as compileRoles,xe as encodeTheme,Wt as layerThemes,It as mergePartials,se as mergeTheme,de as parseAnchorSource,xt as parseTheme,Le as resolveAnchorColor,ut as resolveDataColorSource,Dt as semanticToCSS,Nt as validateTheme,Ft as validateThemePair};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{parseCssColor as
|
|
1
|
+
import{gamutMapToSRGB as A,parseCssColor as g,rotateHue as o}from"./color-engine.js";const x=/^anchor:([^.]+)(?:\.(.+))?$/;function y(n){const r=x.exec(n);return r?r[2]===void 0?{name:r[1]}:{name:r[1],slot:r[2]}:null}function S(n,r){const a=n[r.name];if(a===void 0)return null;if(typeof a=="string")return r.slot===void 0?a:null;const t=a[r.slot??"color"];return typeof t=="string"?t:null}function w(n,r,a){const t=y(n);if(!t)return r[n]??null;const c=S(a,t);return c===null?null:g(c)}const M=.6,_=.85;function H(n,r){const{anchors:a,angles:t,intents:c,semanticHues:i,variantChroma:T}=r,l=u=>T[u]??n.c,e=Math.min(_,Math.max(M,n.l)),s=(u,C)=>{const m=c[u];if(typeof m=="string"){const h=y(m),p=h?S(a,h):m,f=p===null?null:g(p);if(f)return A(f)}return C()};return{primary:n,"analogous-left":{l:n.l,c:l("analogous-left"),h:o(n.h,-t.analogous)},"analogous-right":{l:n.l,c:l("analogous-right"),h:o(n.h,t.analogous)},complementary:{l:n.l,c:l("complementary"),h:o(n.h,t.complementary)},"split-complementary-left":{l:n.l,c:l("split-complementary-left"),h:o(n.h,t.complementary-t.splitComplementary)},"split-complementary-right":{l:n.l,c:l("split-complementary-right"),h:o(n.h,t.complementary+t.splitComplementary)},"triadic-left":{l:n.l,c:l("triadic-left"),h:o(n.h,t.triadic)},"triadic-right":{l:n.l,c:l("triadic-right"),h:o(n.h,-t.triadic)},danger:s("danger",()=>({l:e,c:l("danger"),h:o(i.danger,0)})),success:s("success",()=>({l:e,c:l("success"),h:o(i.success,0)})),warning:s("warning",()=>({l:e,c:l("warning"),h:o(i.warning,0)})),info:s("info",()=>({l:e,c:l("info"),h:o(i.info,0)}))}}export{H as computeVariants,y as parseAnchorSource,S as resolveAnchorColor,w as resolveMappingSource};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@taprootio/espalier",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.1.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",
|
|
@@ -226,6 +226,10 @@
|
|
|
226
226
|
"types": "./dist/status-indicator/esp-status-indicator.d.ts",
|
|
227
227
|
"import": "./dist/status-indicator/esp-status-indicator.js"
|
|
228
228
|
},
|
|
229
|
+
"./switch": {
|
|
230
|
+
"types": "./dist/switch/esp-switch.d.ts",
|
|
231
|
+
"import": "./dist/switch/esp-switch.js"
|
|
232
|
+
},
|
|
229
233
|
"./tabs": {
|
|
230
234
|
"types": "./dist/tabs/esp-tab-group.d.ts",
|
|
231
235
|
"import": "./dist/tabs/esp-tab-group.js"
|